1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Analog Devices.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 3, or (at your
11 option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
28 #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"
43 #include "diagnostic-core.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"
58 #include "sel-sched.h"
61 /* A C structure for machine-specific, per-function data.
62 This is added to the cfun structure. */
63 struct GTY(()) machine_function
65 /* Set if we are notified by the doloop pass that a hardware loop
67 int has_hardware_loops;
69 /* Set if we create a memcpy pattern that uses loop registers. */
70 int has_loopreg_clobber;
73 /* RTX for condition code flag register and RETS register */
74 extern GTY(()) rtx bfin_cc_rtx;
75 extern GTY(()) rtx bfin_rets_rtx;
76 rtx bfin_cc_rtx, bfin_rets_rtx;
78 int max_arg_registers = 0;
80 /* Arrays used when emitting register names. */
81 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
82 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
83 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
84 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
86 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
87 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
89 /* Nonzero if -fschedule-insns2 was given. We override it and
90 call the scheduler ourselves during reorg. */
91 static int bfin_flag_schedule_insns2;
93 /* Determines whether we run variable tracking in machine dependent
95 static int bfin_flag_var_tracking;
102 unsigned int workarounds;
105 static const struct bfin_cpu bfin_cpus[] =
107 {"bf512", BFIN_CPU_BF512, 0x0000,
108 WA_SPECULATIVE_LOADS | WA_05000074},
110 {"bf514", BFIN_CPU_BF514, 0x0000,
111 WA_SPECULATIVE_LOADS | WA_05000074},
113 {"bf516", BFIN_CPU_BF516, 0x0000,
114 WA_SPECULATIVE_LOADS | WA_05000074},
116 {"bf518", BFIN_CPU_BF518, 0x0000,
117 WA_SPECULATIVE_LOADS | WA_05000074},
119 {"bf522", BFIN_CPU_BF522, 0x0002,
120 WA_SPECULATIVE_LOADS | WA_05000074},
121 {"bf522", BFIN_CPU_BF522, 0x0001,
122 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
123 {"bf522", BFIN_CPU_BF522, 0x0000,
124 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
126 {"bf523", BFIN_CPU_BF523, 0x0002,
127 WA_SPECULATIVE_LOADS | WA_05000074},
128 {"bf523", BFIN_CPU_BF523, 0x0001,
129 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
130 {"bf523", BFIN_CPU_BF523, 0x0000,
131 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
133 {"bf524", BFIN_CPU_BF524, 0x0002,
134 WA_SPECULATIVE_LOADS | WA_05000074},
135 {"bf524", BFIN_CPU_BF524, 0x0001,
136 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
137 {"bf524", BFIN_CPU_BF524, 0x0000,
138 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
140 {"bf525", BFIN_CPU_BF525, 0x0002,
141 WA_SPECULATIVE_LOADS | WA_05000074},
142 {"bf525", BFIN_CPU_BF525, 0x0001,
143 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
144 {"bf525", BFIN_CPU_BF525, 0x0000,
145 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
147 {"bf526", BFIN_CPU_BF526, 0x0002,
148 WA_SPECULATIVE_LOADS | WA_05000074},
149 {"bf526", BFIN_CPU_BF526, 0x0001,
150 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
151 {"bf526", BFIN_CPU_BF526, 0x0000,
152 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
154 {"bf527", BFIN_CPU_BF527, 0x0002,
155 WA_SPECULATIVE_LOADS | WA_05000074},
156 {"bf527", BFIN_CPU_BF527, 0x0001,
157 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
158 {"bf527", BFIN_CPU_BF527, 0x0000,
159 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
161 {"bf531", BFIN_CPU_BF531, 0x0006,
162 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
163 {"bf531", BFIN_CPU_BF531, 0x0005,
164 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
165 | WA_LOAD_LCREGS | WA_05000074},
166 {"bf531", BFIN_CPU_BF531, 0x0004,
167 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
168 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
170 {"bf531", BFIN_CPU_BF531, 0x0003,
171 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
172 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
175 {"bf532", BFIN_CPU_BF532, 0x0006,
176 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
177 {"bf532", BFIN_CPU_BF532, 0x0005,
178 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
179 | WA_LOAD_LCREGS | WA_05000074},
180 {"bf532", BFIN_CPU_BF532, 0x0004,
181 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
182 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
184 {"bf532", BFIN_CPU_BF532, 0x0003,
185 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
186 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
189 {"bf533", BFIN_CPU_BF533, 0x0006,
190 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
191 {"bf533", BFIN_CPU_BF533, 0x0005,
192 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
193 | WA_LOAD_LCREGS | WA_05000074},
194 {"bf533", BFIN_CPU_BF533, 0x0004,
195 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
196 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
198 {"bf533", BFIN_CPU_BF533, 0x0003,
199 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
200 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
203 {"bf534", BFIN_CPU_BF534, 0x0003,
204 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
205 {"bf534", BFIN_CPU_BF534, 0x0002,
206 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
207 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
209 {"bf534", BFIN_CPU_BF534, 0x0001,
210 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
211 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
214 {"bf536", BFIN_CPU_BF536, 0x0003,
215 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
216 {"bf536", BFIN_CPU_BF536, 0x0002,
217 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
218 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
220 {"bf536", BFIN_CPU_BF536, 0x0001,
221 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
222 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
225 {"bf537", BFIN_CPU_BF537, 0x0003,
226 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
227 {"bf537", BFIN_CPU_BF537, 0x0002,
228 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
229 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
231 {"bf537", BFIN_CPU_BF537, 0x0001,
232 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
233 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
236 {"bf538", BFIN_CPU_BF538, 0x0005,
237 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
238 {"bf538", BFIN_CPU_BF538, 0x0004,
239 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
240 {"bf538", BFIN_CPU_BF538, 0x0003,
241 WA_SPECULATIVE_LOADS | WA_RETS
242 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
243 {"bf538", BFIN_CPU_BF538, 0x0002,
244 WA_SPECULATIVE_LOADS | WA_RETS
245 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
248 {"bf539", BFIN_CPU_BF539, 0x0005,
249 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
250 {"bf539", BFIN_CPU_BF539, 0x0004,
251 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
252 {"bf539", BFIN_CPU_BF539, 0x0003,
253 WA_SPECULATIVE_LOADS | WA_RETS
254 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
255 {"bf539", BFIN_CPU_BF539, 0x0002,
256 WA_SPECULATIVE_LOADS | WA_RETS
257 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
260 {"bf542m", BFIN_CPU_BF542M, 0x0003,
261 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
263 {"bf542", BFIN_CPU_BF542, 0x0002,
264 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
265 {"bf542", BFIN_CPU_BF542, 0x0001,
266 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
267 {"bf542", BFIN_CPU_BF542, 0x0000,
268 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
271 {"bf544m", BFIN_CPU_BF544M, 0x0003,
272 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
274 {"bf544", BFIN_CPU_BF544, 0x0002,
275 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
276 {"bf544", BFIN_CPU_BF544, 0x0001,
277 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
278 {"bf544", BFIN_CPU_BF544, 0x0000,
279 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
282 {"bf547m", BFIN_CPU_BF547M, 0x0003,
283 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
285 {"bf547", BFIN_CPU_BF547, 0x0002,
286 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
287 {"bf547", BFIN_CPU_BF547, 0x0001,
288 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
289 {"bf547", BFIN_CPU_BF547, 0x0000,
290 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
293 {"bf548m", BFIN_CPU_BF548M, 0x0003,
294 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
296 {"bf548", BFIN_CPU_BF548, 0x0002,
297 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
298 {"bf548", BFIN_CPU_BF548, 0x0001,
299 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
300 {"bf548", BFIN_CPU_BF548, 0x0000,
301 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
304 {"bf549m", BFIN_CPU_BF549M, 0x0003,
305 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
307 {"bf549", BFIN_CPU_BF549, 0x0002,
308 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
309 {"bf549", BFIN_CPU_BF549, 0x0001,
310 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
311 {"bf549", BFIN_CPU_BF549, 0x0000,
312 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
315 {"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS
316 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
317 {"bf561", BFIN_CPU_BF561, 0x0003,
318 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
319 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
321 {"bf561", BFIN_CPU_BF561, 0x0002,
322 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
323 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
326 {NULL, BFIN_CPU_UNKNOWN, 0, 0}
329 int splitting_for_sched, splitting_loops;
332 bfin_globalize_label (FILE *stream, const char *name)
334 fputs (".global ", stream);
335 assemble_name (stream, name);
341 output_file_start (void)
343 FILE *file = asm_out_file;
346 /* Variable tracking should be run after all optimizations which change order
347 of insns. It also needs a valid CFG. This can't be done in
348 bfin_option_override, because flag_var_tracking is finalized after
350 bfin_flag_var_tracking = flag_var_tracking;
351 flag_var_tracking = 0;
353 fprintf (file, ".file \"%s\";\n", input_filename);
355 for (i = 0; arg_regs[i] >= 0; i++)
357 max_arg_registers = i; /* how many arg reg used */
360 /* Examine machine-dependent attributes of function type FUNTYPE and return its
361 type. See the definition of E_FUNKIND. */
364 funkind (const_tree funtype)
366 tree attrs = TYPE_ATTRIBUTES (funtype);
367 if (lookup_attribute ("interrupt_handler", attrs))
368 return INTERRUPT_HANDLER;
369 else if (lookup_attribute ("exception_handler", attrs))
370 return EXCPT_HANDLER;
371 else if (lookup_attribute ("nmi_handler", attrs))
377 /* Legitimize PIC addresses. If the address is already position-independent,
378 we return ORIG. Newly generated position-independent addresses go into a
379 reg. This is REG if nonzero, otherwise we allocate register(s) as
380 necessary. PICREG is the register holding the pointer to the PIC offset
384 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
389 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
394 if (TARGET_ID_SHARED_LIBRARY)
395 unspec = UNSPEC_MOVE_PIC;
396 else if (GET_CODE (addr) == SYMBOL_REF
397 && SYMBOL_REF_FUNCTION_P (addr))
398 unspec = UNSPEC_FUNCDESC_GOT17M4;
400 unspec = UNSPEC_MOVE_FDPIC;
404 gcc_assert (can_create_pseudo_p ());
405 reg = gen_reg_rtx (Pmode);
408 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
409 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
411 emit_move_insn (reg, new_rtx);
412 if (picreg == pic_offset_table_rtx)
413 crtl->uses_pic_offset_table = 1;
417 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
421 if (GET_CODE (addr) == CONST)
423 addr = XEXP (addr, 0);
424 gcc_assert (GET_CODE (addr) == PLUS);
427 if (XEXP (addr, 0) == picreg)
432 gcc_assert (can_create_pseudo_p ());
433 reg = gen_reg_rtx (Pmode);
436 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
437 addr = legitimize_pic_address (XEXP (addr, 1),
438 base == reg ? NULL_RTX : reg,
441 if (GET_CODE (addr) == CONST_INT)
443 gcc_assert (! reload_in_progress && ! reload_completed);
444 addr = force_reg (Pmode, addr);
447 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
449 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
450 addr = XEXP (addr, 1);
453 return gen_rtx_PLUS (Pmode, base, addr);
459 /* Stack frame layout. */
461 /* For a given REGNO, determine whether it must be saved in the function
462 prologue. IS_INTHANDLER specifies whether we're generating a normal
463 prologue or an interrupt/exception one. */
465 must_save_p (bool is_inthandler, unsigned regno)
467 if (D_REGNO_P (regno))
469 bool is_eh_return_reg = false;
470 if (crtl->calls_eh_return)
475 unsigned test = EH_RETURN_DATA_REGNO (j);
476 if (test == INVALID_REGNUM)
479 is_eh_return_reg = true;
483 return (is_eh_return_reg
484 || (df_regs_ever_live_p (regno)
485 && !fixed_regs[regno]
486 && (is_inthandler || !call_used_regs[regno])));
488 else if (P_REGNO_P (regno))
490 return ((df_regs_ever_live_p (regno)
491 && !fixed_regs[regno]
492 && (is_inthandler || !call_used_regs[regno]))
494 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
497 && regno == PIC_OFFSET_TABLE_REGNUM
498 && (crtl->uses_pic_offset_table
499 || (TARGET_ID_SHARED_LIBRARY && !current_function_is_leaf))));
502 return ((is_inthandler || !call_used_regs[regno])
503 && (df_regs_ever_live_p (regno)
504 || (!leaf_function_p () && call_used_regs[regno])));
508 /* Compute the number of DREGS to save with a push_multiple operation.
509 This could include registers that aren't modified in the function,
510 since push_multiple only takes a range of registers.
511 If IS_INTHANDLER, then everything that is live must be saved, even
512 if normally call-clobbered.
513 If CONSECUTIVE, return the number of registers we can save in one
514 instruction with a push/pop multiple instruction. */
517 n_dregs_to_save (bool is_inthandler, bool consecutive)
522 for (i = REG_R7 + 1; i-- != REG_R0;)
524 if (must_save_p (is_inthandler, i))
526 else if (consecutive)
532 /* Like n_dregs_to_save, but compute number of PREGS to save. */
535 n_pregs_to_save (bool is_inthandler, bool consecutive)
540 for (i = REG_P5 + 1; i-- != REG_P0;)
541 if (must_save_p (is_inthandler, i))
543 else if (consecutive)
548 /* Determine if we are going to save the frame pointer in the prologue. */
551 must_save_fp_p (void)
553 return df_regs_ever_live_p (REG_FP);
556 /* Determine if we are going to save the RETS register. */
558 must_save_rets_p (void)
560 return df_regs_ever_live_p (REG_RETS);
564 stack_frame_needed_p (void)
566 /* EH return puts a new return address into the frame using an
567 address relative to the frame pointer. */
568 if (crtl->calls_eh_return)
570 return frame_pointer_needed;
573 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
574 must save all registers; this is used for interrupt handlers.
575 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
576 this for an interrupt (or exception) handler. */
579 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
581 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
582 rtx predec = gen_rtx_MEM (SImode, predec1);
583 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
584 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
585 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
586 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
588 int total_consec = ndregs_consec + npregs_consec;
591 if (saveall || is_inthandler)
593 rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
595 RTX_FRAME_RELATED_P (insn) = 1;
596 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
597 if (! current_function_is_leaf
598 || cfun->machine->has_hardware_loops
599 || cfun->machine->has_loopreg_clobber
600 || (ENABLE_WA_05000257
601 && (dregno == REG_LC0 || dregno == REG_LC1)))
603 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
604 RTX_FRAME_RELATED_P (insn) = 1;
608 if (total_consec != 0)
611 rtx val = GEN_INT (-total_consec * 4);
612 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
614 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
615 UNSPEC_PUSH_MULTIPLE);
616 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg,
620 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
621 d_to_save = ndregs_consec;
622 dregno = REG_R7 + 1 - ndregs_consec;
623 pregno = REG_P5 + 1 - npregs_consec;
624 for (i = 0; i < total_consec; i++)
626 rtx memref = gen_rtx_MEM (word_mode,
627 gen_rtx_PLUS (Pmode, spreg,
628 GEN_INT (- i * 4 - 4)));
632 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
638 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
641 XVECEXP (pat, 0, i + 1) = subpat;
642 RTX_FRAME_RELATED_P (subpat) = 1;
644 insn = emit_insn (pat);
645 RTX_FRAME_RELATED_P (insn) = 1;
648 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
650 if (must_save_p (is_inthandler, dregno))
652 rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
653 RTX_FRAME_RELATED_P (insn) = 1;
657 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
659 if (must_save_p (is_inthandler, pregno))
661 rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
662 RTX_FRAME_RELATED_P (insn) = 1;
666 for (i = REG_P7 + 1; i < REG_CC; i++)
669 && (df_regs_ever_live_p (i)
670 || (!leaf_function_p () && call_used_regs[i]))))
673 if (i == REG_A0 || i == REG_A1)
674 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
675 gen_rtx_REG (PDImode, i));
677 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
678 RTX_FRAME_RELATED_P (insn) = 1;
682 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
683 must save all registers; this is used for interrupt handlers.
684 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
685 this for an interrupt (or exception) handler. */
688 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
690 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
691 rtx postinc = gen_rtx_MEM (SImode, postinc1);
693 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
694 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
695 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
696 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
697 int total_consec = ndregs_consec + npregs_consec;
701 /* A slightly crude technique to stop flow from trying to delete "dead"
703 MEM_VOLATILE_P (postinc) = 1;
705 for (i = REG_CC - 1; i > REG_P7; i--)
708 && (df_regs_ever_live_p (i)
709 || (!leaf_function_p () && call_used_regs[i]))))
711 if (i == REG_A0 || i == REG_A1)
713 rtx mem = gen_rtx_MEM (PDImode, postinc1);
714 MEM_VOLATILE_P (mem) = 1;
715 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
718 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
721 regno = REG_P5 - npregs_consec;
722 for (; npregs != npregs_consec; regno--)
724 if (must_save_p (is_inthandler, regno))
726 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
730 regno = REG_R7 - ndregs_consec;
731 for (; ndregs != ndregs_consec; regno--)
733 if (must_save_p (is_inthandler, regno))
735 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
740 if (total_consec != 0)
742 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
744 = gen_rtx_SET (VOIDmode, spreg,
745 gen_rtx_PLUS (Pmode, spreg,
746 GEN_INT (total_consec * 4)));
748 if (npregs_consec > 0)
753 for (i = 0; i < total_consec; i++)
756 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
758 rtx memref = gen_rtx_MEM (word_mode, addr);
761 XVECEXP (pat, 0, i + 1)
762 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
764 if (npregs_consec > 0)
766 if (--npregs_consec == 0)
771 insn = emit_insn (pat);
772 RTX_FRAME_RELATED_P (insn) = 1;
774 if (saveall || is_inthandler)
776 for (regno = REG_LB1; regno >= REG_LT0; regno--)
777 if (! current_function_is_leaf
778 || cfun->machine->has_hardware_loops
779 || cfun->machine->has_loopreg_clobber
780 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
781 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
783 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
787 /* Perform any needed actions needed for a function that is receiving a
788 variable number of arguments.
792 MODE and TYPE are the mode and type of the current parameter.
794 PRETEND_SIZE is a variable that should be set to the amount of stack
795 that must be pushed by the prolog to pretend that our caller pushed
798 Normally, this macro will push all remaining incoming registers on the
799 stack and set PRETEND_SIZE to the length of the registers pushed.
802 - VDSP C compiler manual (our ABI) says that a variable args function
803 should save the R0, R1 and R2 registers in the stack.
804 - The caller will always leave space on the stack for the
805 arguments that are passed in registers, so we dont have
806 to leave any extra space.
807 - now, the vastart pointer can access all arguments from the stack. */
810 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
811 enum machine_mode mode ATTRIBUTE_UNUSED,
812 tree type ATTRIBUTE_UNUSED, int *pretend_size,
821 /* The move for named arguments will be generated automatically by the
822 compiler. We need to generate the move rtx for the unnamed arguments
823 if they are in the first 3 words. We assume at least 1 named argument
824 exists, so we never generate [ARGP] = R0 here. */
826 for (i = cum->words + 1; i < max_arg_registers; i++)
828 mem = gen_rtx_MEM (Pmode,
829 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
830 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
836 /* Value should be nonzero if functions must have frame pointers.
837 Zero means the frame pointer need not be set up (and parms may
838 be accessed via the stack pointer) in functions that seem suitable. */
841 bfin_frame_pointer_required (void)
843 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
845 if (fkind != SUBROUTINE)
848 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
849 so we have to override it for non-leaf functions. */
850 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
856 /* Return the number of registers pushed during the prologue. */
859 n_regs_saved_by_prologue (void)
861 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
862 bool is_inthandler = fkind != SUBROUTINE;
863 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
864 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
865 || (is_inthandler && !current_function_is_leaf));
866 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
867 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
868 int n = ndregs + npregs;
871 if (all || stack_frame_needed_p ())
875 if (must_save_fp_p ())
877 if (must_save_rets_p ())
881 if (fkind != SUBROUTINE || all)
883 /* Increment once for ASTAT. */
885 if (! current_function_is_leaf
886 || cfun->machine->has_hardware_loops
887 || cfun->machine->has_loopreg_clobber)
893 if (fkind != SUBROUTINE)
896 if (lookup_attribute ("nesting", attrs))
900 for (i = REG_P7 + 1; i < REG_CC; i++)
902 || (fkind != SUBROUTINE
903 && (df_regs_ever_live_p (i)
904 || (!leaf_function_p () && call_used_regs[i]))))
905 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
910 /* Given FROM and TO register numbers, say whether this elimination is
911 allowed. Frame pointer elimination is automatically handled.
913 All other eliminations are valid. */
916 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
918 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
921 /* Return the offset between two registers, one to be eliminated, and the other
922 its replacement, at the start of a routine. */
925 bfin_initial_elimination_offset (int from, int to)
927 HOST_WIDE_INT offset = 0;
929 if (from == ARG_POINTER_REGNUM)
930 offset = n_regs_saved_by_prologue () * 4;
932 if (to == STACK_POINTER_REGNUM)
934 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
935 offset += crtl->outgoing_args_size;
936 else if (crtl->outgoing_args_size)
937 offset += FIXED_STACK_AREA;
939 offset += get_frame_size ();
945 /* Emit code to load a constant CONSTANT into register REG; setting
946 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
947 Make sure that the insns we generate need not be split. */
950 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
953 rtx cst = GEN_INT (constant);
955 if (constant >= -32768 && constant < 65536)
956 insn = emit_move_insn (reg, cst);
959 /* We don't call split_load_immediate here, since dwarf2out.c can get
960 confused about some of the more clever sequences it can generate. */
961 insn = emit_insn (gen_movsi_high (reg, cst));
963 RTX_FRAME_RELATED_P (insn) = 1;
964 insn = emit_insn (gen_movsi_low (reg, reg, cst));
967 RTX_FRAME_RELATED_P (insn) = 1;
970 /* Generate efficient code to add a value to a P register.
971 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
972 EPILOGUE_P is zero if this function is called for prologue,
973 otherwise it's nonzero. And it's less than zero if this is for
977 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
982 /* Choose whether to use a sequence using a temporary register, or
983 a sequence with multiple adds. We can add a signed 7-bit value
984 in one instruction. */
985 if (value > 120 || value < -120)
993 /* For prologue or normal epilogue, P1 can be safely used
994 as the temporary register. For sibcall epilogue, we try to find
995 a call used P register, which will be restored in epilogue.
996 If we cannot find such a P register, we have to use one I register
1000 tmpreg = gen_rtx_REG (SImode, REG_P1);
1004 for (i = REG_P0; i <= REG_P5; i++)
1005 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
1007 && i == PIC_OFFSET_TABLE_REGNUM
1008 && (crtl->uses_pic_offset_table
1009 || (TARGET_ID_SHARED_LIBRARY
1010 && ! current_function_is_leaf))))
1013 tmpreg = gen_rtx_REG (SImode, i);
1016 tmpreg = gen_rtx_REG (SImode, REG_P1);
1017 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
1018 emit_move_insn (tmpreg2, tmpreg);
1023 frame_related_constant_load (tmpreg, value, TRUE);
1025 insn = emit_move_insn (tmpreg, GEN_INT (value));
1027 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
1029 RTX_FRAME_RELATED_P (insn) = 1;
1031 if (tmpreg2 != NULL_RTX)
1032 emit_move_insn (tmpreg, tmpreg2);
1042 else if (size < -60)
1043 /* We could use -62, but that would leave the stack unaligned, so
1047 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
1049 RTX_FRAME_RELATED_P (insn) = 1;
1055 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
1056 is too large, generate a sequence of insns that has the same effect.
1057 SPREG contains (reg:SI REG_SP). */
1060 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
1062 HOST_WIDE_INT link_size = frame_size;
1066 if (link_size > 262140)
1069 /* Use a LINK insn with as big a constant as possible, then subtract
1070 any remaining size from the SP. */
1071 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
1072 RTX_FRAME_RELATED_P (insn) = 1;
1074 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1076 rtx set = XVECEXP (PATTERN (insn), 0, i);
1077 gcc_assert (GET_CODE (set) == SET);
1078 RTX_FRAME_RELATED_P (set) = 1;
1081 frame_size -= link_size;
1085 /* Must use a call-clobbered PREG that isn't the static chain. */
1086 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
1088 frame_related_constant_load (tmpreg, -frame_size, TRUE);
1089 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
1090 RTX_FRAME_RELATED_P (insn) = 1;
1094 /* Return the number of bytes we must reserve for outgoing arguments
1095 in the current function's stack frame. */
1097 static HOST_WIDE_INT
1098 arg_area_size (void)
1100 if (crtl->outgoing_args_size)
1102 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
1103 return crtl->outgoing_args_size;
1105 return FIXED_STACK_AREA;
1110 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
1111 function must save all its registers (true only for certain interrupt
1115 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
1117 frame_size += arg_area_size ();
1120 || stack_frame_needed_p ()
1121 || (must_save_rets_p () && must_save_fp_p ()))
1122 emit_link_insn (spreg, frame_size);
1125 if (must_save_rets_p ())
1127 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1128 gen_rtx_PRE_DEC (Pmode, spreg)),
1130 rtx insn = emit_insn (pat);
1131 RTX_FRAME_RELATED_P (insn) = 1;
1133 if (must_save_fp_p ())
1135 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1136 gen_rtx_PRE_DEC (Pmode, spreg)),
1137 gen_rtx_REG (Pmode, REG_FP));
1138 rtx insn = emit_insn (pat);
1139 RTX_FRAME_RELATED_P (insn) = 1;
1141 add_to_reg (spreg, -frame_size, 1, 0);
1145 /* Like do_link, but used for epilogues to deallocate the stack frame.
1146 EPILOGUE_P is zero if this function is called for prologue,
1147 otherwise it's nonzero. And it's less than zero if this is for
1148 sibcall epilogue. */
1151 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
1153 frame_size += arg_area_size ();
1155 if (stack_frame_needed_p ())
1156 emit_insn (gen_unlink ());
1159 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
1161 add_to_reg (spreg, frame_size, 0, epilogue_p);
1162 if (all || must_save_fp_p ())
1164 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
1165 emit_move_insn (fpreg, postinc);
1168 if (all || must_save_rets_p ())
1170 emit_move_insn (bfin_rets_rtx, postinc);
1171 emit_use (bfin_rets_rtx);
1176 /* Generate a prologue suitable for a function of kind FKIND. This is
1177 called for interrupt and exception handler prologues.
1178 SPREG contains (reg:SI REG_SP). */
1181 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
1183 HOST_WIDE_INT frame_size = get_frame_size ();
1184 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
1185 rtx predec = gen_rtx_MEM (SImode, predec1);
1187 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1188 tree kspisusp = lookup_attribute ("kspisusp", attrs);
1192 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
1193 RTX_FRAME_RELATED_P (insn) = 1;
1196 /* We need space on the stack in case we need to save the argument
1198 if (fkind == EXCPT_HANDLER)
1200 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
1201 RTX_FRAME_RELATED_P (insn) = 1;
1204 /* If we're calling other functions, they won't save their call-clobbered
1205 registers, so we must save everything here. */
1206 if (!current_function_is_leaf)
1208 expand_prologue_reg_save (spreg, all, true);
1210 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
1212 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
1213 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
1214 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
1215 emit_insn (gen_movsi_high (p5reg, chipid));
1216 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
1217 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
1220 if (lookup_attribute ("nesting", attrs))
1222 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1223 insn = emit_move_insn (predec, srcreg);
1224 RTX_FRAME_RELATED_P (insn) = 1;
1227 do_link (spreg, frame_size, all);
1229 if (fkind == EXCPT_HANDLER)
1231 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
1232 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
1233 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
1235 emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
1236 emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
1237 emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
1238 emit_move_insn (r1reg, spreg);
1239 emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
1240 emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
1244 /* Generate an epilogue suitable for a function of kind FKIND. This is
1245 called for interrupt and exception handler epilogues.
1246 SPREG contains (reg:SI REG_SP). */
1249 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1251 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1252 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1253 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1255 /* A slightly crude technique to stop flow from trying to delete "dead"
1257 MEM_VOLATILE_P (postinc) = 1;
1259 do_unlink (spreg, get_frame_size (), all, 1);
1261 if (lookup_attribute ("nesting", attrs))
1263 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1264 emit_move_insn (srcreg, postinc);
1267 /* If we're calling other functions, they won't save their call-clobbered
1268 registers, so we must save (and restore) everything here. */
1269 if (!current_function_is_leaf)
1272 expand_epilogue_reg_restore (spreg, all, true);
1274 /* Deallocate any space we left on the stack in case we needed to save the
1275 argument registers. */
1276 if (fkind == EXCPT_HANDLER)
1277 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1279 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1282 /* Used while emitting the prologue to generate code to load the correct value
1283 into the PIC register, which is passed in DEST. */
1286 bfin_load_pic_reg (rtx dest)
1288 struct cgraph_local_info *i = NULL;
1291 i = cgraph_local_info (current_function_decl);
1293 /* Functions local to the translation unit don't need to reload the
1294 pic reg, since the caller always passes a usable one. */
1296 return pic_offset_table_rtx;
1298 if (global_options_set.x_bfin_library_id)
1299 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
1301 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1302 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1303 UNSPEC_LIBRARY_OFFSET));
1304 emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1308 /* Generate RTL for the prologue of the current function. */
1311 bfin_expand_prologue (void)
1313 HOST_WIDE_INT frame_size = get_frame_size ();
1314 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1315 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1316 rtx pic_reg_loaded = NULL_RTX;
1317 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1318 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1320 if (fkind != SUBROUTINE)
1322 expand_interrupt_handler_prologue (spreg, fkind, all);
1326 if (crtl->limit_stack
1327 || (TARGET_STACK_CHECK_L1
1328 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1330 HOST_WIDE_INT offset
1331 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1332 STACK_POINTER_REGNUM);
1333 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1334 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1338 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1339 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1342 if (GET_CODE (lim) == SYMBOL_REF)
1344 if (TARGET_ID_SHARED_LIBRARY)
1346 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1348 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1349 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1351 emit_move_insn (p1reg, val);
1352 frame_related_constant_load (p2reg, offset, FALSE);
1353 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1358 rtx limit = plus_constant (lim, offset);
1359 emit_move_insn (p2reg, limit);
1366 emit_move_insn (p2reg, lim);
1367 add_to_reg (p2reg, offset, 0, 0);
1370 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1371 emit_insn (gen_trapifcc ());
1373 expand_prologue_reg_save (spreg, all, false);
1375 do_link (spreg, frame_size, all);
1377 if (TARGET_ID_SHARED_LIBRARY
1379 && (crtl->uses_pic_offset_table
1380 || !current_function_is_leaf))
1381 bfin_load_pic_reg (pic_offset_table_rtx);
1384 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1385 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1386 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1390 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1392 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1393 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1394 int e = sibcall_p ? -1 : 1;
1395 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1396 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1398 if (fkind != SUBROUTINE)
1400 expand_interrupt_handler_epilogue (spreg, fkind, all);
1404 do_unlink (spreg, get_frame_size (), all, e);
1406 expand_epilogue_reg_restore (spreg, all, false);
1408 /* Omit the return insn if this is for a sibcall. */
1413 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1415 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1418 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1421 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1422 unsigned int new_reg)
1424 /* Interrupt functions can only use registers that have already been
1425 saved by the prologue, even if they would normally be
1428 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1429 && !df_regs_ever_live_p (new_reg))
1435 /* Return the value of the return address for the frame COUNT steps up
1436 from the current frame, after the prologue.
1437 We punt for everything but the current frame by returning const0_rtx. */
1440 bfin_return_addr_rtx (int count)
1445 return get_hard_reg_initial_val (Pmode, REG_RETS);
1449 bfin_delegitimize_address (rtx orig_x)
1453 if (GET_CODE (x) != MEM)
1457 if (GET_CODE (x) == PLUS
1458 && GET_CODE (XEXP (x, 1)) == UNSPEC
1459 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1460 && GET_CODE (XEXP (x, 0)) == REG
1461 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1462 return XVECEXP (XEXP (x, 1), 0, 0);
1467 /* This predicate is used to compute the length of a load/store insn.
1468 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1469 32-bit instruction. */
1472 effective_address_32bit_p (rtx op, enum machine_mode mode)
1474 HOST_WIDE_INT offset;
1476 mode = GET_MODE (op);
1479 if (GET_CODE (op) != PLUS)
1481 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1482 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1486 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1489 offset = INTVAL (XEXP (op, 1));
1491 /* All byte loads use a 16-bit offset. */
1492 if (GET_MODE_SIZE (mode) == 1)
1495 if (GET_MODE_SIZE (mode) == 4)
1497 /* Frame pointer relative loads can use a negative offset, all others
1498 are restricted to a small positive one. */
1499 if (XEXP (op, 0) == frame_pointer_rtx)
1500 return offset < -128 || offset > 60;
1501 return offset < 0 || offset > 60;
1504 /* Must be HImode now. */
1505 return offset < 0 || offset > 30;
1508 /* Returns true if X is a memory reference using an I register. */
1510 bfin_dsp_memref_p (rtx x)
1515 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1516 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1521 /* Return cost of the memory address ADDR.
1522 All addressing modes are equally cheap on the Blackfin. */
1525 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED)
1530 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1533 print_address_operand (FILE *file, rtx x)
1535 switch (GET_CODE (x))
1538 output_address (XEXP (x, 0));
1539 fprintf (file, "+");
1540 output_address (XEXP (x, 1));
1544 fprintf (file, "--");
1545 output_address (XEXP (x, 0));
1548 output_address (XEXP (x, 0));
1549 fprintf (file, "++");
1552 output_address (XEXP (x, 0));
1553 fprintf (file, "--");
1557 gcc_assert (GET_CODE (x) != MEM);
1558 print_operand (file, x, 0);
1563 /* Adding intp DImode support by Tony
1569 print_operand (FILE *file, rtx x, char code)
1571 enum machine_mode mode;
1575 if (GET_MODE (current_output_insn) == SImode)
1576 fprintf (file, " ||");
1578 fprintf (file, ";");
1582 mode = GET_MODE (x);
1587 switch (GET_CODE (x))
1590 fprintf (file, "e");
1593 fprintf (file, "ne");
1596 fprintf (file, "g");
1599 fprintf (file, "l");
1602 fprintf (file, "ge");
1605 fprintf (file, "le");
1608 fprintf (file, "g");
1611 fprintf (file, "l");
1614 fprintf (file, "ge");
1617 fprintf (file, "le");
1620 output_operand_lossage ("invalid %%j value");
1624 case 'J': /* reverse logic */
1625 switch (GET_CODE(x))
1628 fprintf (file, "ne");
1631 fprintf (file, "e");
1634 fprintf (file, "le");
1637 fprintf (file, "ge");
1640 fprintf (file, "l");
1643 fprintf (file, "g");
1646 fprintf (file, "le");
1649 fprintf (file, "ge");
1652 fprintf (file, "l");
1655 fprintf (file, "g");
1658 output_operand_lossage ("invalid %%J value");
1663 switch (GET_CODE (x))
1669 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1671 output_operand_lossage ("invalid operand for code '%c'", code);
1673 else if (code == 'd')
1676 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1678 output_operand_lossage ("invalid operand for code '%c'", code);
1680 else if (code == 'w')
1682 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1683 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1685 output_operand_lossage ("invalid operand for code '%c'", code);
1687 else if (code == 'x')
1689 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1690 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1692 output_operand_lossage ("invalid operand for code '%c'", code);
1694 else if (code == 'v')
1696 if (REGNO (x) == REG_A0)
1697 fprintf (file, "AV0");
1698 else if (REGNO (x) == REG_A1)
1699 fprintf (file, "AV1");
1701 output_operand_lossage ("invalid operand for code '%c'", code);
1703 else if (code == 'D')
1705 if (D_REGNO_P (REGNO (x)))
1706 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1708 output_operand_lossage ("invalid operand for code '%c'", code);
1710 else if (code == 'H')
1712 if ((mode == DImode || mode == DFmode) && REG_P (x))
1713 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1715 output_operand_lossage ("invalid operand for code '%c'", code);
1717 else if (code == 'T')
1719 if (D_REGNO_P (REGNO (x)))
1720 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1722 output_operand_lossage ("invalid operand for code '%c'", code);
1725 fprintf (file, "%s", reg_names[REGNO (x)]);
1731 print_address_operand (file, x);
1743 fputs ("(FU)", file);
1746 fputs ("(T)", file);
1749 fputs ("(TFU)", file);
1752 fputs ("(W32)", file);
1755 fputs ("(IS)", file);
1758 fputs ("(IU)", file);
1761 fputs ("(IH)", file);
1764 fputs ("(M)", file);
1767 fputs ("(IS,M)", file);
1770 fputs ("(ISS2)", file);
1773 fputs ("(S2RND)", file);
1780 else if (code == 'b')
1782 if (INTVAL (x) == 0)
1784 else if (INTVAL (x) == 1)
1790 /* Moves to half registers with d or h modifiers always use unsigned
1792 else if (code == 'd')
1793 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1794 else if (code == 'h')
1795 x = GEN_INT (INTVAL (x) & 0xffff);
1796 else if (code == 'N')
1797 x = GEN_INT (-INTVAL (x));
1798 else if (code == 'X')
1799 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1800 else if (code == 'Y')
1801 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1802 else if (code == 'Z')
1803 /* Used for LINK insns. */
1804 x = GEN_INT (-8 - INTVAL (x));
1809 output_addr_const (file, x);
1813 output_operand_lossage ("invalid const_double operand");
1817 switch (XINT (x, 1))
1819 case UNSPEC_MOVE_PIC:
1820 output_addr_const (file, XVECEXP (x, 0, 0));
1821 fprintf (file, "@GOT");
1824 case UNSPEC_MOVE_FDPIC:
1825 output_addr_const (file, XVECEXP (x, 0, 0));
1826 fprintf (file, "@GOT17M4");
1829 case UNSPEC_FUNCDESC_GOT17M4:
1830 output_addr_const (file, XVECEXP (x, 0, 0));
1831 fprintf (file, "@FUNCDESC_GOT17M4");
1834 case UNSPEC_LIBRARY_OFFSET:
1835 fprintf (file, "_current_shared_library_p5_offset_");
1844 output_addr_const (file, x);
1849 /* Argument support functions. */
1851 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1852 for a call to a function whose data type is FNTYPE.
1853 For a library call, FNTYPE is 0.
1854 VDSP C Compiler manual, our ABI says that
1855 first 3 words of arguments will use R0, R1 and R2.
1859 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1860 rtx libname ATTRIBUTE_UNUSED)
1862 static CUMULATIVE_ARGS zero_cum;
1866 /* Set up the number of registers to use for passing arguments. */
1868 cum->nregs = max_arg_registers;
1869 cum->arg_regs = arg_regs;
1871 cum->call_cookie = CALL_NORMAL;
1872 /* Check for a longcall attribute. */
1873 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1874 cum->call_cookie |= CALL_SHORT;
1875 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1876 cum->call_cookie |= CALL_LONG;
1881 /* Update the data in CUM to advance over an argument
1882 of mode MODE and data type TYPE.
1883 (TYPE is null for libcalls where that information may not be available.) */
1886 bfin_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1887 const_tree type, bool named ATTRIBUTE_UNUSED)
1889 int count, bytes, words;
1891 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1892 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1894 cum->words += words;
1895 cum->nregs -= words;
1897 if (cum->nregs <= 0)
1900 cum->arg_regs = NULL;
1904 for (count = 1; count <= words; count++)
1911 /* Define where to put the arguments to a function.
1912 Value is zero to push the argument on the stack,
1913 or a hard register in which to store the argument.
1915 MODE is the argument's machine mode.
1916 TYPE is the data type of the argument (as a tree).
1917 This is null for libcalls where that information may
1919 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1920 the preceding args and about the function being called.
1921 NAMED is nonzero if this argument is a named parameter
1922 (otherwise it is an extra parameter matching an ellipsis). */
1925 bfin_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1926 const_tree type, bool named ATTRIBUTE_UNUSED)
1929 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1931 if (mode == VOIDmode)
1932 /* Compute operand 2 of the call insn. */
1933 return GEN_INT (cum->call_cookie);
1939 return gen_rtx_REG (mode, *(cum->arg_regs));
1944 /* For an arg passed partly in registers and partly in memory,
1945 this is the number of bytes passed in registers.
1946 For args passed entirely in registers or entirely in memory, zero.
1948 Refer VDSP C Compiler manual, our ABI.
1949 First 3 words are in registers. So, if an argument is larger
1950 than the registers available, it will span the register and
1954 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1955 tree type ATTRIBUTE_UNUSED,
1956 bool named ATTRIBUTE_UNUSED)
1959 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1960 int bytes_left = cum->nregs * UNITS_PER_WORD;
1965 if (bytes_left == 0)
1967 if (bytes > bytes_left)
1972 /* Variable sized types are passed by reference. */
1975 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1976 enum machine_mode mode ATTRIBUTE_UNUSED,
1977 const_tree type, bool named ATTRIBUTE_UNUSED)
1979 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1982 /* Decide whether a type should be returned in memory (true)
1983 or in a register (false). This is called by the macro
1984 TARGET_RETURN_IN_MEMORY. */
1987 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1989 int size = int_size_in_bytes (type);
1990 return size > 2 * UNITS_PER_WORD || size == -1;
1993 /* Register in which address to store a structure value
1994 is passed to a function. */
1996 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1997 int incoming ATTRIBUTE_UNUSED)
1999 return gen_rtx_REG (Pmode, REG_P0);
2002 /* Return true when register may be used to pass function parameters. */
2005 function_arg_regno_p (int n)
2008 for (i = 0; arg_regs[i] != -1; i++)
2009 if (n == arg_regs[i])
2014 /* Returns 1 if OP contains a symbol reference */
2017 symbolic_reference_mentioned_p (rtx op)
2019 register const char *fmt;
2022 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
2025 fmt = GET_RTX_FORMAT (GET_CODE (op));
2026 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
2032 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
2033 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
2037 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
2044 /* Decide whether we can make a sibling call to a function. DECL is the
2045 declaration of the function being targeted by the call and EXP is the
2046 CALL_EXPR representing the call. */
2049 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
2050 tree exp ATTRIBUTE_UNUSED)
2052 struct cgraph_local_info *this_func, *called_func;
2053 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
2054 if (fkind != SUBROUTINE)
2056 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
2059 /* When compiling for ID shared libraries, can't sibcall a local function
2060 from a non-local function, because the local function thinks it does
2061 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
2062 sibcall epilogue, and we end up with the wrong value in P5. */
2065 /* Not enough information. */
2068 this_func = cgraph_local_info (current_function_decl);
2069 called_func = cgraph_local_info (decl);
2070 return !called_func->local || this_func->local;
2073 /* Write a template for a trampoline to F. */
2076 bfin_asm_trampoline_template (FILE *f)
2080 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
2081 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
2082 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
2083 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
2084 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
2085 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
2086 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
2087 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
2088 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
2092 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
2093 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
2094 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
2095 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
2096 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
2100 /* Emit RTL insns to initialize the variable parts of a trampoline at
2101 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
2102 the static chain value for the function. */
2105 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2107 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
2108 rtx t2 = copy_to_reg (chain_value);
2112 emit_block_move (m_tramp, assemble_trampoline_template (),
2113 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2117 rtx a = force_reg (Pmode, plus_constant (XEXP (m_tramp, 0), 8));
2118 mem = adjust_address (m_tramp, Pmode, 0);
2119 emit_move_insn (mem, a);
2123 mem = adjust_address (m_tramp, HImode, i + 2);
2124 emit_move_insn (mem, gen_lowpart (HImode, t1));
2125 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
2126 mem = adjust_address (m_tramp, HImode, i + 6);
2127 emit_move_insn (mem, gen_lowpart (HImode, t1));
2129 mem = adjust_address (m_tramp, HImode, i + 10);
2130 emit_move_insn (mem, gen_lowpart (HImode, t2));
2131 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
2132 mem = adjust_address (m_tramp, HImode, i + 14);
2133 emit_move_insn (mem, gen_lowpart (HImode, t2));
2136 /* Emit insns to move operands[1] into operands[0]. */
2139 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
2141 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2143 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
2144 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2145 operands[1] = force_reg (SImode, operands[1]);
2147 operands[1] = legitimize_pic_address (operands[1], temp,
2148 TARGET_FDPIC ? OUR_FDPIC_REG
2149 : pic_offset_table_rtx);
2152 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
2153 Returns true if no further code must be generated, false if the caller
2154 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
2157 expand_move (rtx *operands, enum machine_mode mode)
2159 rtx op = operands[1];
2160 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
2161 && SYMBOLIC_CONST (op))
2162 emit_pic_move (operands, mode);
2163 else if (mode == SImode && GET_CODE (op) == CONST
2164 && GET_CODE (XEXP (op, 0)) == PLUS
2165 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
2166 && !bfin_legitimate_constant_p (op))
2168 rtx dest = operands[0];
2170 gcc_assert (!reload_in_progress && !reload_completed);
2172 op0 = force_reg (mode, XEXP (op, 0));
2174 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
2175 op1 = force_reg (mode, op1);
2176 if (GET_CODE (dest) == MEM)
2177 dest = gen_reg_rtx (mode);
2178 emit_insn (gen_addsi3 (dest, op0, op1));
2179 if (dest == operands[0])
2183 /* Don't generate memory->memory or constant->memory moves, go through a
2185 else if ((reload_in_progress | reload_completed) == 0
2186 && GET_CODE (operands[0]) == MEM
2187 && GET_CODE (operands[1]) != REG)
2188 operands[1] = force_reg (mode, operands[1]);
2192 /* Split one or more DImode RTL references into pairs of SImode
2193 references. The RTL can be REG, offsettable MEM, integer constant, or
2194 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2195 split and "num" is its length. lo_half and hi_half are output arrays
2196 that parallel "operands". */
2199 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
2203 rtx op = operands[num];
2205 /* simplify_subreg refuse to split volatile memory addresses,
2206 but we still have to handle it. */
2207 if (GET_CODE (op) == MEM)
2209 lo_half[num] = adjust_address (op, SImode, 0);
2210 hi_half[num] = adjust_address (op, SImode, 4);
2214 lo_half[num] = simplify_gen_subreg (SImode, op,
2215 GET_MODE (op) == VOIDmode
2216 ? DImode : GET_MODE (op), 0);
2217 hi_half[num] = simplify_gen_subreg (SImode, op,
2218 GET_MODE (op) == VOIDmode
2219 ? DImode : GET_MODE (op), 4);
2225 bfin_longcall_p (rtx op, int call_cookie)
2227 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2228 if (SYMBOL_REF_WEAK (op))
2230 if (call_cookie & CALL_SHORT)
2232 if (call_cookie & CALL_LONG)
2234 if (TARGET_LONG_CALLS)
2239 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2240 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2241 SIBCALL is nonzero if this is a sibling call. */
2244 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2246 rtx use = NULL, call;
2247 rtx callee = XEXP (fnaddr, 0);
2250 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2251 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2254 /* In an untyped call, we can get NULL for operand 2. */
2255 if (cookie == NULL_RTX)
2256 cookie = const0_rtx;
2258 /* Static functions and indirect calls don't need the pic register. */
2259 if (!TARGET_FDPIC && flag_pic
2260 && GET_CODE (callee) == SYMBOL_REF
2261 && !SYMBOL_REF_LOCAL_P (callee))
2262 use_reg (&use, pic_offset_table_rtx);
2266 int caller_in_sram, callee_in_sram;
2268 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2269 caller_in_sram = callee_in_sram = 0;
2271 if (lookup_attribute ("l1_text",
2272 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2274 else if (lookup_attribute ("l2",
2275 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2278 if (GET_CODE (callee) == SYMBOL_REF
2279 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2281 if (lookup_attribute
2283 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2285 else if (lookup_attribute
2287 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2291 if (GET_CODE (callee) != SYMBOL_REF
2292 || bfin_longcall_p (callee, INTVAL (cookie))
2293 || (GET_CODE (callee) == SYMBOL_REF
2294 && !SYMBOL_REF_LOCAL_P (callee)
2295 && TARGET_INLINE_PLT)
2296 || caller_in_sram != callee_in_sram
2297 || (caller_in_sram && callee_in_sram
2298 && (GET_CODE (callee) != SYMBOL_REF
2299 || !SYMBOL_REF_LOCAL_P (callee))))
2302 if (! address_operand (addr, Pmode))
2303 addr = force_reg (Pmode, addr);
2305 fnaddr = gen_reg_rtx (SImode);
2306 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2307 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2309 picreg = gen_reg_rtx (SImode);
2310 emit_insn (gen_load_funcdescsi (picreg,
2311 plus_constant (addr, 4)));
2316 else if ((!register_no_elim_operand (callee, Pmode)
2317 && GET_CODE (callee) != SYMBOL_REF)
2318 || (GET_CODE (callee) == SYMBOL_REF
2319 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2320 || bfin_longcall_p (callee, INTVAL (cookie)))))
2322 callee = copy_to_mode_reg (Pmode, callee);
2323 fnaddr = gen_rtx_MEM (Pmode, callee);
2325 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2328 call = gen_rtx_SET (VOIDmode, retval, call);
2330 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2332 XVECEXP (pat, 0, n++) = call;
2334 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2335 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2337 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
2339 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2340 call = emit_call_insn (pat);
2342 CALL_INSN_FUNCTION_USAGE (call) = use;
2345 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2348 hard_regno_mode_ok (int regno, enum machine_mode mode)
2350 /* Allow only dregs to store value of mode HI or QI */
2351 enum reg_class rclass = REGNO_REG_CLASS (regno);
2356 if (mode == V2HImode)
2357 return D_REGNO_P (regno);
2358 if (rclass == CCREGS)
2359 return mode == BImode;
2360 if (mode == PDImode || mode == V2PDImode)
2361 return regno == REG_A0 || regno == REG_A1;
2363 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2364 up with a bad register class (such as ALL_REGS) for DImode. */
2366 return regno < REG_M3;
2369 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2372 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2375 /* Implements target hook vector_mode_supported_p. */
2378 bfin_vector_mode_supported_p (enum machine_mode mode)
2380 return mode == V2HImode;
2383 /* Return the cost of moving data from a register in class CLASS1 to
2384 one in class CLASS2. A cost of 2 is the default. */
2387 bfin_register_move_cost (enum machine_mode mode,
2388 enum reg_class class1, enum reg_class class2)
2390 /* These need secondary reloads, so they're more expensive. */
2391 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2392 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2395 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2399 if (GET_MODE_CLASS (mode) == MODE_INT)
2401 /* Discourage trying to use the accumulators. */
2402 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2403 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2404 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2405 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2411 /* Return the cost of moving data of mode M between a
2412 register and memory. A value of 2 is the default; this cost is
2413 relative to those in `REGISTER_MOVE_COST'.
2415 ??? In theory L1 memory has single-cycle latency. We should add a switch
2416 that tells the compiler whether we expect to use only L1 memory for the
2417 program; it'll make the costs more accurate. */
2420 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2421 enum reg_class rclass,
2422 int in ATTRIBUTE_UNUSED)
2424 /* Make memory accesses slightly more expensive than any register-register
2425 move. Also, penalize non-DP registers, since they need secondary
2426 reloads to load and store. */
2427 if (! reg_class_subset_p (rclass, DPREGS))
2433 /* Inform reload about cases where moving X with a mode MODE to a register in
2434 RCLASS requires an extra scratch register. Return the class needed for the
2435 scratch register. */
2438 bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
2439 enum machine_mode mode, secondary_reload_info *sri)
2441 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2442 in most other cases we can also use PREGS. */
2443 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2444 enum reg_class x_class = NO_REGS;
2445 enum rtx_code code = GET_CODE (x);
2446 enum reg_class rclass = (enum reg_class) rclass_i;
2449 x = SUBREG_REG (x), code = GET_CODE (x);
2452 int regno = REGNO (x);
2453 if (regno >= FIRST_PSEUDO_REGISTER)
2454 regno = reg_renumber[regno];
2459 x_class = REGNO_REG_CLASS (regno);
2462 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2463 This happens as a side effect of register elimination, and we need
2464 a scratch register to do it. */
2465 if (fp_plus_const_operand (x, mode))
2467 rtx op2 = XEXP (x, 1);
2468 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2470 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2472 /* If destination is a DREG, we can do this without a scratch register
2473 if the constant is valid for an add instruction. */
2474 if ((rclass == DREGS || rclass == DPREGS)
2475 && ! large_constant_p)
2477 /* Reloading to anything other than a DREG? Use a PREG scratch
2479 sri->icode = CODE_FOR_reload_insi;
2483 /* Data can usually be moved freely between registers of most classes.
2484 AREGS are an exception; they can only move to or from another register
2485 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2486 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2487 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2488 || rclass == ODD_AREGS
2491 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2495 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2499 if (x != const0_rtx && x_class != DREGS)
2507 /* CCREGS can only be moved from/to DREGS. */
2508 if (rclass == CCREGS && x_class != DREGS)
2510 if (x_class == CCREGS && rclass != DREGS)
2513 /* All registers other than AREGS can load arbitrary constants. The only
2514 case that remains is MEM. */
2516 if (! reg_class_subset_p (rclass, default_class))
2517 return default_class;
2522 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2525 bfin_class_likely_spilled_p (reg_class_t rclass)
2529 case PREGS_CLOBBERED:
2545 /* Implement TARGET_HANDLE_OPTION. */
2548 bfin_handle_option (struct gcc_options *opts,
2549 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
2550 const struct cl_decoded_option *decoded,
2553 size_t code = decoded->opt_index;
2554 const char *arg = decoded->arg;
2555 int value = decoded->value;
2559 case OPT_mshared_library_id_:
2560 if (value > MAX_LIBRARY_ID)
2561 error_at (loc, "-mshared-library-id=%s is not between 0 and %d",
2562 arg, MAX_LIBRARY_ID);
2571 while ((p = bfin_cpus[i].name) != NULL)
2573 if (strncmp (arg, p, strlen (p)) == 0)
2580 error_at (loc, "-mcpu=%s is not valid", arg);
2584 opts->x_bfin_cpu_type = bfin_cpus[i].type;
2586 q = arg + strlen (p);
2590 opts->x_bfin_si_revision = bfin_cpus[i].si_revision;
2591 opts->x_bfin_workarounds |= bfin_cpus[i].workarounds;
2593 else if (strcmp (q, "-none") == 0)
2594 opts->x_bfin_si_revision = -1;
2595 else if (strcmp (q, "-any") == 0)
2597 opts->x_bfin_si_revision = 0xffff;
2598 while (bfin_cpus[i].type == opts->x_bfin_cpu_type)
2600 opts->x_bfin_workarounds |= bfin_cpus[i].workarounds;
2606 unsigned int si_major, si_minor;
2609 rev_len = strlen (q);
2611 if (sscanf (q, "-%u.%u%n", &si_major, &si_minor, &n) != 2
2613 || si_major > 0xff || si_minor > 0xff)
2615 invalid_silicon_revision:
2616 error_at (loc, "-mcpu=%s has invalid silicon revision", arg);
2620 opts->x_bfin_si_revision = (si_major << 8) | si_minor;
2622 while (bfin_cpus[i].type == opts->x_bfin_cpu_type
2623 && bfin_cpus[i].si_revision != opts->x_bfin_si_revision)
2626 if (bfin_cpus[i].type != opts->x_bfin_cpu_type)
2627 goto invalid_silicon_revision;
2629 opts->x_bfin_workarounds |= bfin_cpus[i].workarounds;
2640 static struct machine_function *
2641 bfin_init_machine_status (void)
2643 return ggc_alloc_cleared_machine_function ();
2646 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2649 bfin_option_override (void)
2651 /* If processor type is not specified, enable all workarounds. */
2652 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2656 for (i = 0; bfin_cpus[i].name != NULL; i++)
2657 bfin_workarounds |= bfin_cpus[i].workarounds;
2659 bfin_si_revision = 0xffff;
2662 if (bfin_csync_anomaly == 1)
2663 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2664 else if (bfin_csync_anomaly == 0)
2665 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2667 if (bfin_specld_anomaly == 1)
2668 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2669 else if (bfin_specld_anomaly == 0)
2670 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2672 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2673 flag_omit_frame_pointer = 1;
2675 /* Library identification */
2676 if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY)
2677 error ("-mshared-library-id= specified without -mid-shared-library");
2679 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2680 error ("can%'t use multiple stack checking methods together");
2682 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2683 error ("ID shared libraries and FD-PIC mode can%'t be used together");
2685 /* Don't allow the user to specify -mid-shared-library and -msep-data
2686 together, as it makes little sense from a user's point of view... */
2687 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2688 error ("cannot specify both -msep-data and -mid-shared-library");
2689 /* ... internally, however, it's nearly the same. */
2690 if (TARGET_SEP_DATA)
2691 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2693 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2696 /* There is no single unaligned SI op for PIC code. Sometimes we
2697 need to use ".4byte" and sometimes we need to use ".picptr".
2698 See bfin_assemble_integer for details. */
2700 targetm.asm_out.unaligned_op.si = 0;
2702 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2703 since we don't support it and it'll just break. */
2704 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2707 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2708 error ("-mmulticore can only be used with BF561");
2710 if (TARGET_COREA && !TARGET_MULTICORE)
2711 error ("-mcorea should be used with -mmulticore");
2713 if (TARGET_COREB && !TARGET_MULTICORE)
2714 error ("-mcoreb should be used with -mmulticore");
2716 if (TARGET_COREA && TARGET_COREB)
2717 error ("-mcorea and -mcoreb can%'t be used together");
2719 flag_schedule_insns = 0;
2721 /* Passes after sched2 can break the helpful TImode annotations that
2722 haifa-sched puts on every insn. Just do scheduling in reorg. */
2723 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2724 flag_schedule_insns_after_reload = 0;
2726 init_machine_status = bfin_init_machine_status;
2729 /* Return the destination address of BRANCH.
2730 We need to use this instead of get_attr_length, because the
2731 cbranch_with_nops pattern conservatively sets its length to 6, and
2732 we still prefer to use shorter sequences. */
2735 branch_dest (rtx branch)
2739 rtx pat = PATTERN (branch);
2740 if (GET_CODE (pat) == PARALLEL)
2741 pat = XVECEXP (pat, 0, 0);
2742 dest = SET_SRC (pat);
2743 if (GET_CODE (dest) == IF_THEN_ELSE)
2744 dest = XEXP (dest, 1);
2745 dest = XEXP (dest, 0);
2746 dest_uid = INSN_UID (dest);
2747 return INSN_ADDRESSES (dest_uid);
2750 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2751 it's a branch that's predicted taken. */
2754 cbranch_predicted_taken_p (rtx insn)
2756 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2760 int pred_val = INTVAL (XEXP (x, 0));
2762 return pred_val >= REG_BR_PROB_BASE / 2;
2768 /* Templates for use by asm_conditional_branch. */
2770 static const char *ccbranch_templates[][3] = {
2771 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2772 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2773 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2774 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2777 /* Output INSN, which is a conditional branch instruction with operands
2780 We deal with the various forms of conditional branches that can be generated
2781 by bfin_reorg to prevent the hardware from doing speculative loads, by
2782 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2783 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2784 Either of these is only necessary if the branch is short, otherwise the
2785 template we use ends in an unconditional jump which flushes the pipeline
2789 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2791 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2792 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2793 is to be taken from start of if cc rather than jump.
2794 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2796 int len = (offset >= -1024 && offset <= 1022 ? 0
2797 : offset >= -4094 && offset <= 4096 ? 1
2799 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2800 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2801 output_asm_insn (ccbranch_templates[idx][len], operands);
2802 gcc_assert (n_nops == 0 || !bp);
2804 while (n_nops-- > 0)
2805 output_asm_insn ("nop;", NULL);
2808 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2809 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2812 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2814 enum rtx_code code1, code2;
2815 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2816 rtx tem = bfin_cc_rtx;
2817 enum rtx_code code = GET_CODE (cmp);
2819 /* If we have a BImode input, then we already have a compare result, and
2820 do not need to emit another comparison. */
2821 if (GET_MODE (op0) == BImode)
2823 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2824 tem = op0, code2 = code;
2829 /* bfin has these conditions */
2839 code1 = reverse_condition (code);
2843 emit_insn (gen_rtx_SET (VOIDmode, tem,
2844 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2847 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2850 /* Return nonzero iff C has exactly one bit set if it is interpreted
2851 as a 32-bit constant. */
2854 log2constp (unsigned HOST_WIDE_INT c)
2857 return c != 0 && (c & (c-1)) == 0;
2860 /* Returns the number of consecutive least significant zeros in the binary
2861 representation of *V.
2862 We modify *V to contain the original value arithmetically shifted right by
2863 the number of zeroes. */
2866 shiftr_zero (HOST_WIDE_INT *v)
2868 unsigned HOST_WIDE_INT tmp = *v;
2869 unsigned HOST_WIDE_INT sgn;
2875 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2876 while ((tmp & 0x1) == 0 && n <= 32)
2878 tmp = (tmp >> 1) | sgn;
2885 /* After reload, split the load of an immediate constant. OPERANDS are the
2886 operands of the movsi_insn pattern which we are splitting. We return
2887 nonzero if we emitted a sequence to load the constant, zero if we emitted
2888 nothing because we want to use the splitter's default sequence. */
2891 split_load_immediate (rtx operands[])
2893 HOST_WIDE_INT val = INTVAL (operands[1]);
2895 HOST_WIDE_INT shifted = val;
2896 HOST_WIDE_INT shifted_compl = ~val;
2897 int num_zero = shiftr_zero (&shifted);
2898 int num_compl_zero = shiftr_zero (&shifted_compl);
2899 unsigned int regno = REGNO (operands[0]);
2901 /* This case takes care of single-bit set/clear constants, which we could
2902 also implement with BITSET/BITCLR. */
2904 && shifted >= -32768 && shifted < 65536
2905 && (D_REGNO_P (regno)
2906 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2908 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2909 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2914 tmp |= -(tmp & 0x8000);
2916 /* If high word has one bit set or clear, try to use a bit operation. */
2917 if (D_REGNO_P (regno))
2919 if (log2constp (val & 0xFFFF0000))
2921 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2922 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2925 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2927 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2928 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2932 if (D_REGNO_P (regno))
2934 if (tmp >= -64 && tmp <= 63)
2936 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2937 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2941 if ((val & 0xFFFF0000) == 0)
2943 emit_insn (gen_movsi (operands[0], const0_rtx));
2944 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2948 if ((val & 0xFFFF0000) == 0xFFFF0000)
2950 emit_insn (gen_movsi (operands[0], constm1_rtx));
2951 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2956 /* Need DREGs for the remaining case. */
2961 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2963 /* If optimizing for size, generate a sequence that has more instructions
2965 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2966 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2967 GEN_INT (num_compl_zero)));
2968 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2974 /* Return true if the legitimate memory address for a memory operand of mode
2975 MODE. Return false if not. */
2978 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2980 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2981 int sz = GET_MODE_SIZE (mode);
2982 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2983 /* The usual offsettable_memref machinery doesn't work so well for this
2984 port, so we deal with the problem here. */
2985 if (value > 0 && sz == 8)
2987 return (v & ~(0x7fff << shift)) == 0;
2991 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2992 enum rtx_code outer_code)
2995 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2997 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
3000 /* Recognize an RTL expression that is a valid memory address for an
3001 instruction. The MODE argument is the machine mode for the MEM expression
3002 that wants to use this address.
3004 Blackfin addressing modes are as follows:
3010 W [ Preg + uimm16m2 ]
3019 bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
3021 switch (GET_CODE (x)) {
3023 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
3027 if (REG_P (XEXP (x, 0))
3028 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
3029 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
3030 || (GET_CODE (XEXP (x, 1)) == CONST_INT
3031 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
3036 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
3037 && REG_P (XEXP (x, 0))
3038 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
3041 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
3042 && XEXP (x, 0) == stack_pointer_rtx
3043 && REG_P (XEXP (x, 0))
3044 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
3053 /* Decide whether we can force certain constants to memory. If we
3054 decide we can't, the caller should be able to cope with it in
3058 bfin_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
3059 rtx x ATTRIBUTE_UNUSED)
3061 /* We have only one class of non-legitimate constants, and our movsi
3062 expander knows how to handle them. Dropping these constants into the
3063 data section would only shift the problem - we'd still get relocs
3064 outside the object, in the data section rather than the text section. */
3068 /* Ensure that for any constant of the form symbol + offset, the offset
3069 remains within the object. Any other constants are ok.
3070 This ensures that flat binaries never have to deal with relocations
3071 crossing section boundaries. */
3074 bfin_legitimate_constant_p (rtx x)
3077 HOST_WIDE_INT offset;
3079 if (GET_CODE (x) != CONST)
3083 gcc_assert (GET_CODE (x) == PLUS);
3087 if (GET_CODE (sym) != SYMBOL_REF
3088 || GET_CODE (x) != CONST_INT)
3090 offset = INTVAL (x);
3092 if (SYMBOL_REF_DECL (sym) == 0)
3095 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
3102 bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int *total, bool speed)
3104 enum rtx_code code = (enum rtx_code) code_i;
3105 enum rtx_code outer_code = (enum rtx_code) outer_code_i;
3106 int cost2 = COSTS_N_INSNS (1);
3112 if (outer_code == SET || outer_code == PLUS)
3113 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
3114 else if (outer_code == AND)
3115 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
3116 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
3117 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
3118 else if (outer_code == LEU || outer_code == LTU)
3119 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
3120 else if (outer_code == MULT)
3121 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
3122 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
3124 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
3125 || outer_code == LSHIFTRT)
3126 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
3127 else if (outer_code == IOR || outer_code == XOR)
3128 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
3137 *total = COSTS_N_INSNS (2);
3143 if (GET_MODE (x) == SImode)
3145 if (GET_CODE (op0) == MULT
3146 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
3148 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
3149 if (val == 2 || val == 4)
3152 *total += rtx_cost (XEXP (op0, 0), outer_code, speed);
3153 *total += rtx_cost (op1, outer_code, speed);
3158 if (GET_CODE (op0) != REG
3159 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3160 *total += rtx_cost (op0, SET, speed);
3161 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
3162 towards creating too many induction variables. */
3163 if (!reg_or_7bit_operand (op1, SImode))
3164 *total += rtx_cost (op1, SET, speed);
3167 else if (GET_MODE (x) == DImode)
3170 if (GET_CODE (op1) != CONST_INT
3171 || !satisfies_constraint_Ks7 (op1))
3172 *total += rtx_cost (op1, PLUS, speed);
3173 if (GET_CODE (op0) != REG
3174 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3175 *total += rtx_cost (op0, PLUS, speed);
3180 if (GET_MODE (x) == DImode)
3189 if (GET_MODE (x) == DImode)
3196 if (GET_CODE (op0) != REG
3197 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3198 *total += rtx_cost (op0, code, speed);
3208 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
3211 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
3212 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
3213 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
3214 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
3221 if (GET_CODE (op0) != REG
3222 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3223 *total += rtx_cost (op0, code, speed);
3225 if (GET_MODE (x) == DImode)
3231 if (GET_MODE (x) != SImode)
3236 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
3237 *total += rtx_cost (XEXP (x, 1), code, speed);
3241 if (! regorlog2_operand (XEXP (x, 1), SImode))
3242 *total += rtx_cost (XEXP (x, 1), code, speed);
3249 if (outer_code == SET
3250 && XEXP (x, 1) == const1_rtx
3251 && GET_CODE (XEXP (x, 2)) == CONST_INT)
3267 if (GET_CODE (op0) == GET_CODE (op1)
3268 && (GET_CODE (op0) == ZERO_EXTEND
3269 || GET_CODE (op0) == SIGN_EXTEND))
3271 *total = COSTS_N_INSNS (1);
3272 op0 = XEXP (op0, 0);
3273 op1 = XEXP (op1, 0);
3276 *total = COSTS_N_INSNS (1);
3278 *total = COSTS_N_INSNS (3);
3280 if (GET_CODE (op0) != REG
3281 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3282 *total += rtx_cost (op0, MULT, speed);
3283 if (GET_CODE (op1) != REG
3284 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3285 *total += rtx_cost (op1, MULT, speed);
3291 *total = COSTS_N_INSNS (32);
3296 if (outer_code == SET)
3305 /* Used for communication between {push,pop}_multiple_operation (which
3306 we use not only as a predicate) and the corresponding output functions. */
3307 static int first_preg_to_save, first_dreg_to_save;
3308 static int n_regs_to_save;
3311 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3313 int lastdreg = 8, lastpreg = 6;
3316 first_preg_to_save = lastpreg;
3317 first_dreg_to_save = lastdreg;
3318 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3320 rtx t = XVECEXP (op, 0, i);
3324 if (GET_CODE (t) != SET)
3328 dest = SET_DEST (t);
3329 if (GET_CODE (dest) != MEM || ! REG_P (src))
3331 dest = XEXP (dest, 0);
3332 if (GET_CODE (dest) != PLUS
3333 || ! REG_P (XEXP (dest, 0))
3334 || REGNO (XEXP (dest, 0)) != REG_SP
3335 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3336 || INTVAL (XEXP (dest, 1)) != -i * 4)
3339 regno = REGNO (src);
3342 if (D_REGNO_P (regno))
3345 first_dreg_to_save = lastdreg = regno - REG_R0;
3347 else if (regno >= REG_P0 && regno <= REG_P7)
3350 first_preg_to_save = lastpreg = regno - REG_P0;
3360 if (regno >= REG_P0 && regno <= REG_P7)
3363 first_preg_to_save = lastpreg = regno - REG_P0;
3365 else if (regno != REG_R0 + lastdreg + 1)
3370 else if (group == 2)
3372 if (regno != REG_P0 + lastpreg + 1)
3377 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3382 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3384 int lastdreg = 8, lastpreg = 6;
3387 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3389 rtx t = XVECEXP (op, 0, i);
3393 if (GET_CODE (t) != SET)
3397 dest = SET_DEST (t);
3398 if (GET_CODE (src) != MEM || ! REG_P (dest))
3400 src = XEXP (src, 0);
3404 if (! REG_P (src) || REGNO (src) != REG_SP)
3407 else if (GET_CODE (src) != PLUS
3408 || ! REG_P (XEXP (src, 0))
3409 || REGNO (XEXP (src, 0)) != REG_SP
3410 || GET_CODE (XEXP (src, 1)) != CONST_INT
3411 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3414 regno = REGNO (dest);
3417 if (regno == REG_R7)
3422 else if (regno != REG_P0 + lastpreg - 1)
3427 else if (group == 1)
3429 if (regno != REG_R0 + lastdreg - 1)
3435 first_dreg_to_save = lastdreg;
3436 first_preg_to_save = lastpreg;
3437 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3441 /* Emit assembly code for one multi-register push described by INSN, with
3442 operands in OPERANDS. */
3445 output_push_multiple (rtx insn, rtx *operands)
3450 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3451 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3454 if (first_dreg_to_save == 8)
3455 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3456 else if (first_preg_to_save == 6)
3457 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3459 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3460 first_dreg_to_save, first_preg_to_save);
3462 output_asm_insn (buf, operands);
3465 /* Emit assembly code for one multi-register pop described by INSN, with
3466 operands in OPERANDS. */
3469 output_pop_multiple (rtx insn, rtx *operands)
3474 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3475 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3478 if (first_dreg_to_save == 8)
3479 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3480 else if (first_preg_to_save == 6)
3481 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3483 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3484 first_dreg_to_save, first_preg_to_save);
3486 output_asm_insn (buf, operands);
3489 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3492 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3494 rtx scratch = gen_reg_rtx (mode);
3497 srcmem = adjust_address_nv (src, mode, offset);
3498 dstmem = adjust_address_nv (dst, mode, offset);
3499 emit_move_insn (scratch, srcmem);
3500 emit_move_insn (dstmem, scratch);
3503 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3504 alignment ALIGN_EXP. Return true if successful, false if we should fall
3505 back on a different method. */
3508 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3510 rtx srcreg, destreg, countreg;
3511 HOST_WIDE_INT align = 0;
3512 unsigned HOST_WIDE_INT count = 0;
3514 if (GET_CODE (align_exp) == CONST_INT)
3515 align = INTVAL (align_exp);
3516 if (GET_CODE (count_exp) == CONST_INT)
3518 count = INTVAL (count_exp);
3520 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3525 /* If optimizing for size, only do single copies inline. */
3528 if (count == 2 && align < 2)
3530 if (count == 4 && align < 4)
3532 if (count != 1 && count != 2 && count != 4)
3535 if (align < 2 && count != 1)
3538 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3539 if (destreg != XEXP (dst, 0))
3540 dst = replace_equiv_address_nv (dst, destreg);
3541 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3542 if (srcreg != XEXP (src, 0))
3543 src = replace_equiv_address_nv (src, srcreg);
3545 if (count != 0 && align >= 2)
3547 unsigned HOST_WIDE_INT offset = 0;
3551 if ((count & ~3) == 4)
3553 single_move_for_movmem (dst, src, SImode, offset);
3556 else if (count & ~3)
3558 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3559 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3561 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3562 cfun->machine->has_loopreg_clobber = true;
3566 single_move_for_movmem (dst, src, HImode, offset);
3572 if ((count & ~1) == 2)
3574 single_move_for_movmem (dst, src, HImode, offset);
3577 else if (count & ~1)
3579 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3580 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3582 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3583 cfun->machine->has_loopreg_clobber = true;
3588 single_move_for_movmem (dst, src, QImode, offset);
3595 /* Compute the alignment for a local variable.
3596 TYPE is the data type, and ALIGN is the alignment that
3597 the object would ordinarily have. The value of this macro is used
3598 instead of that alignment to align the object. */
3601 bfin_local_alignment (tree type, unsigned align)
3603 /* Increasing alignment for (relatively) big types allows the builtin
3604 memcpy can use 32 bit loads/stores. */
3605 if (TYPE_SIZE (type)
3606 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3607 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3608 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3613 /* Implement TARGET_SCHED_ISSUE_RATE. */
3616 bfin_issue_rate (void)
3622 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3624 enum attr_type dep_insn_type;
3625 int dep_insn_code_number;
3627 /* Anti and output dependencies have zero cost. */
3628 if (REG_NOTE_KIND (link) != 0)
3631 dep_insn_code_number = recog_memoized (dep_insn);
3633 /* If we can't recognize the insns, we can't really do anything. */
3634 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3637 dep_insn_type = get_attr_type (dep_insn);
3639 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3641 rtx pat = PATTERN (dep_insn);
3644 if (GET_CODE (pat) == PARALLEL)
3645 pat = XVECEXP (pat, 0, 0);
3646 dest = SET_DEST (pat);
3647 src = SET_SRC (pat);
3648 if (! ADDRESS_REGNO_P (REGNO (dest))
3649 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3651 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3657 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3658 skips all subsequent parallel instructions if INSN is the start of such
3661 find_next_insn_start (rtx insn)
3663 if (GET_MODE (insn) == SImode)
3665 while (GET_MODE (insn) != QImode)
3666 insn = NEXT_INSN (insn);
3668 return NEXT_INSN (insn);
3671 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3672 skips all subsequent parallel instructions if INSN is the start of such
3675 find_prev_insn_start (rtx insn)
3677 insn = PREV_INSN (insn);
3678 gcc_assert (GET_MODE (insn) != SImode);
3679 if (GET_MODE (insn) == QImode)
3681 while (GET_MODE (PREV_INSN (insn)) == SImode)
3682 insn = PREV_INSN (insn);
3687 /* Increment the counter for the number of loop instructions in the
3688 current function. */
3691 bfin_hardware_loop (void)
3693 cfun->machine->has_hardware_loops++;
3696 /* Maximum loop nesting depth. */
3697 #define MAX_LOOP_DEPTH 2
3699 /* Maximum size of a loop. */
3700 #define MAX_LOOP_LENGTH 2042
3702 /* Maximum distance of the LSETUP instruction from the loop start. */
3703 #define MAX_LSETUP_DISTANCE 30
3705 /* We need to keep a vector of loops */
3706 typedef struct loop_info_d *loop_info;
3707 DEF_VEC_P (loop_info);
3708 DEF_VEC_ALLOC_P (loop_info,heap);
3710 /* Information about a loop we have found (or are in the process of
3712 struct GTY (()) loop_info_d
3714 /* loop number, for dumps */
3717 /* All edges that jump into and out of the loop. */
3718 VEC(edge,gc) *incoming;
3720 /* We can handle two cases: all incoming edges have the same destination
3721 block, or all incoming edges have the same source block. These two
3722 members are set to the common source or destination we found, or NULL
3723 if different blocks were found. If both are NULL the loop can't be
3725 basic_block incoming_src;
3726 basic_block incoming_dest;
3728 /* First block in the loop. This is the one branched to by the loop_end
3732 /* Last block in the loop (the one with the loop_end insn). */
3735 /* The successor block of the loop. This is the one the loop_end insn
3737 basic_block successor;
3739 /* The last instruction in the tail. */
3742 /* The loop_end insn. */
3745 /* The iteration register. */
3748 /* The new label placed at the beginning of the loop. */
3751 /* The new label placed at the end of the loop. */
3754 /* The length of the loop. */
3757 /* The nesting depth of the loop. */
3760 /* Nonzero if we can't optimize this loop. */
3763 /* True if we have visited this loop. */
3766 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3769 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3772 /* Next loop in the graph. */
3773 struct loop_info_d *next;
3775 /* Immediate outer loop of this loop. */
3776 struct loop_info_d *outer;
3778 /* Vector of blocks only within the loop, including those within
3780 VEC (basic_block,heap) *blocks;
3782 /* Same information in a bitmap. */
3783 bitmap block_bitmap;
3785 /* Vector of inner loops within this loop */
3786 VEC (loop_info,heap) *loops;
3790 bfin_dump_loops (loop_info loops)
3794 for (loop = loops; loop; loop = loop->next)
3800 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3802 fprintf (dump_file, "(bad) ");
3803 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3805 fprintf (dump_file, " blocks: [ ");
3806 FOR_EACH_VEC_ELT (basic_block, loop->blocks, ix, b)
3807 fprintf (dump_file, "%d ", b->index);
3808 fprintf (dump_file, "] ");
3810 fprintf (dump_file, " inner loops: [ ");
3811 FOR_EACH_VEC_ELT (loop_info, loop->loops, ix, i)
3812 fprintf (dump_file, "%d ", i->loop_no);
3813 fprintf (dump_file, "]\n");
3815 fprintf (dump_file, "\n");
3818 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3819 BB. Return true, if we find it. */
3822 bfin_bb_in_loop (loop_info loop, basic_block bb)
3824 return bitmap_bit_p (loop->block_bitmap, bb->index);
3827 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3828 REG. Return true, if we find any. Don't count the loop's loop_end
3829 insn if it matches LOOP_END. */
3832 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3837 FOR_EACH_VEC_ELT (basic_block, loop->blocks, ix, bb)
3841 for (insn = BB_HEAD (bb);
3842 insn != NEXT_INSN (BB_END (bb));
3843 insn = NEXT_INSN (insn))
3847 if (insn == loop_end)
3849 if (reg_mentioned_p (reg, PATTERN (insn)))
3856 /* Estimate the length of INSN conservatively. */
3859 length_for_loop (rtx insn)
3862 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3864 if (ENABLE_WA_SPECULATIVE_SYNCS)
3866 else if (ENABLE_WA_SPECULATIVE_LOADS)
3869 else if (LABEL_P (insn))
3871 if (ENABLE_WA_SPECULATIVE_SYNCS)
3875 if (NONDEBUG_INSN_P (insn))
3876 length += get_attr_length (insn);
3881 /* Optimize LOOP. */
3884 bfin_optimize_loop (loop_info loop)
3888 rtx insn, last_insn;
3889 rtx loop_init, start_label, end_label;
3890 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3891 rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
3892 rtx lc_reg, lt_reg, lb_reg;
3896 int inner_depth = 0;
3906 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3910 /* Every loop contains in its list of inner loops every loop nested inside
3911 it, even if there are intermediate loops. This works because we're doing
3912 a depth-first search here and never visit a loop more than once. */
3913 FOR_EACH_VEC_ELT (loop_info, loop->loops, ix, inner)
3915 bfin_optimize_loop (inner);
3917 if (!inner->bad && inner_depth < inner->depth)
3919 inner_depth = inner->depth;
3921 loop->clobber_loop0 |= inner->clobber_loop0;
3922 loop->clobber_loop1 |= inner->clobber_loop1;
3926 loop->depth = inner_depth + 1;
3927 if (loop->depth > MAX_LOOP_DEPTH)
3930 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3934 /* Get the loop iteration register. */
3935 iter_reg = loop->iter_reg;
3937 if (!REG_P (iter_reg))
3940 fprintf (dump_file, ";; loop %d iteration count not in a register\n",
3944 scratchreg = NULL_RTX;
3945 scratch_init = iter_reg;
3946 scratch_init_insn = NULL_RTX;
3947 if (!PREG_P (iter_reg) && loop->incoming_src)
3949 basic_block bb_in = loop->incoming_src;
3951 for (i = REG_P0; i <= REG_P5; i++)
3952 if ((df_regs_ever_live_p (i)
3953 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3954 && call_used_regs[i]))
3955 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3957 scratchreg = gen_rtx_REG (SImode, i);
3960 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3961 insn = PREV_INSN (insn))
3964 if (NOTE_P (insn) || BARRIER_P (insn))
3966 set = single_set (insn);
3967 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3969 if (CONSTANT_P (SET_SRC (set)))
3971 scratch_init = SET_SRC (set);
3972 scratch_init_insn = insn;
3976 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3981 if (loop->incoming_src)
3983 /* Make sure the predecessor is before the loop start label, as required by
3984 the LSETUP instruction. */
3986 insn = BB_END (loop->incoming_src);
3987 /* If we have to insert the LSETUP before a jump, count that jump in the
3989 if (VEC_length (edge, loop->incoming) > 1
3990 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3992 gcc_assert (JUMP_P (insn));
3993 insn = PREV_INSN (insn);
3996 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3997 length += length_for_loop (insn);
4002 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
4007 /* Account for the pop of a scratch register where necessary. */
4008 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
4009 && ENABLE_WA_LOAD_LCREGS)
4012 if (length > MAX_LSETUP_DISTANCE)
4015 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
4020 /* Check if start_label appears before loop_end and calculate the
4021 offset between them. We calculate the length of instructions
4024 for (insn = loop->start_label;
4025 insn && insn != loop->loop_end;
4026 insn = NEXT_INSN (insn))
4027 length += length_for_loop (insn);
4032 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
4037 loop->length = length;
4038 if (loop->length > MAX_LOOP_LENGTH)
4041 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4045 /* Scan all the blocks to make sure they don't use iter_reg. */
4046 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
4049 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
4053 /* Scan all the insns to see if the loop body clobber
4054 any hardware loop registers. */
4056 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
4057 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
4058 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
4059 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
4060 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
4061 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
4063 FOR_EACH_VEC_ELT (basic_block, loop->blocks, ix, bb)
4067 for (insn = BB_HEAD (bb);
4068 insn != NEXT_INSN (BB_END (bb));
4069 insn = NEXT_INSN (insn))
4074 if (reg_set_p (reg_lc0, insn)
4075 || reg_set_p (reg_lt0, insn)
4076 || reg_set_p (reg_lb0, insn))
4077 loop->clobber_loop0 = 1;
4079 if (reg_set_p (reg_lc1, insn)
4080 || reg_set_p (reg_lt1, insn)
4081 || reg_set_p (reg_lb1, insn))
4082 loop->clobber_loop1 |= 1;
4086 if ((loop->clobber_loop0 && loop->clobber_loop1)
4087 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
4089 loop->depth = MAX_LOOP_DEPTH + 1;
4091 fprintf (dump_file, ";; loop %d no loop reg available\n",
4096 /* There should be an instruction before the loop_end instruction
4097 in the same basic block. And the instruction must not be
4099 - CONDITIONAL BRANCH
4103 - Returns (RTS, RTN, etc.) */
4106 last_insn = find_prev_insn_start (loop->loop_end);
4110 for (; last_insn != BB_HEAD (bb);
4111 last_insn = find_prev_insn_start (last_insn))
4112 if (NONDEBUG_INSN_P (last_insn))
4115 if (last_insn != BB_HEAD (bb))
4118 if (single_pred_p (bb)
4119 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
4120 && single_pred (bb) != ENTRY_BLOCK_PTR)
4122 bb = single_pred (bb);
4123 last_insn = BB_END (bb);
4128 last_insn = NULL_RTX;
4136 fprintf (dump_file, ";; loop %d has no last instruction\n",
4141 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
4144 fprintf (dump_file, ";; loop %d has bad last instruction\n",
4148 /* In all other cases, try to replace a bad last insn with a nop. */
4149 else if (JUMP_P (last_insn)
4150 || CALL_P (last_insn)
4151 || get_attr_type (last_insn) == TYPE_SYNC
4152 || get_attr_type (last_insn) == TYPE_CALL
4153 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
4154 || recog_memoized (last_insn) == CODE_FOR_return_internal
4155 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
4156 || asm_noperands (PATTERN (last_insn)) >= 0)
4158 if (loop->length + 2 > MAX_LOOP_LENGTH)
4161 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4165 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
4168 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
4171 loop->last_insn = last_insn;
4173 /* The loop is good for replacement. */
4174 start_label = loop->start_label;
4175 end_label = gen_label_rtx ();
4176 iter_reg = loop->iter_reg;
4178 if (loop->depth == 1 && !loop->clobber_loop1)
4183 loop->clobber_loop1 = 1;
4190 loop->clobber_loop0 = 1;
4193 loop->end_label = end_label;
4195 /* Create a sequence containing the loop setup. */
4198 /* LSETUP only accepts P registers. If we have one, we can use it,
4199 otherwise there are several ways of working around the problem.
4200 If we're not affected by anomaly 312, we can load the LC register
4201 from any iteration register, and use LSETUP without initialization.
4202 If we've found a P scratch register that's not live here, we can
4203 instead copy the iter_reg into that and use an initializing LSETUP.
4204 If all else fails, push and pop P0 and use it as a scratch. */
4205 if (P_REGNO_P (REGNO (iter_reg)))
4207 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4210 seq_end = emit_insn (loop_init);
4212 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
4214 emit_insn (gen_movsi (lc_reg, iter_reg));
4215 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
4218 seq_end = emit_insn (loop_init);
4220 else if (scratchreg != NULL_RTX)
4222 emit_insn (gen_movsi (scratchreg, scratch_init));
4223 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4225 lc_reg, scratchreg);
4226 seq_end = emit_insn (loop_init);
4227 if (scratch_init_insn != NULL_RTX)
4228 delete_insn (scratch_init_insn);
4232 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
4233 rtx push = gen_frame_mem (SImode,
4234 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
4235 rtx pop = gen_frame_mem (SImode,
4236 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
4237 emit_insn (gen_movsi (push, p0reg));
4238 emit_insn (gen_movsi (p0reg, scratch_init));
4239 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4242 emit_insn (loop_init);
4243 seq_end = emit_insn (gen_movsi (p0reg, pop));
4244 if (scratch_init_insn != NULL_RTX)
4245 delete_insn (scratch_init_insn);
4250 fprintf (dump_file, ";; replacing loop %d initializer with\n",
4252 print_rtl_single (dump_file, loop_init);
4253 fprintf (dump_file, ";; replacing loop %d terminator with\n",
4255 print_rtl_single (dump_file, loop->loop_end);
4258 /* If the loop isn't entered at the top, also create a jump to the entry
4260 if (!loop->incoming_src && loop->head != loop->incoming_dest)
4262 rtx label = BB_HEAD (loop->incoming_dest);
4263 /* If we're jumping to the final basic block in the loop, and there's
4264 only one cheap instruction before the end (typically an increment of
4265 an induction variable), we can just emit a copy here instead of a
4267 if (loop->incoming_dest == loop->tail
4268 && next_real_insn (label) == last_insn
4269 && asm_noperands (last_insn) < 0
4270 && GET_CODE (PATTERN (last_insn)) == SET)
4272 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
4276 emit_jump_insn (gen_jump (label));
4277 seq_end = emit_barrier ();
4284 if (loop->incoming_src)
4286 rtx prev = BB_END (loop->incoming_src);
4287 if (VEC_length (edge, loop->incoming) > 1
4288 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
4290 gcc_assert (JUMP_P (prev));
4291 prev = PREV_INSN (prev);
4293 emit_insn_after (seq, prev);
4301 #ifdef ENABLE_CHECKING
4302 if (loop->head != loop->incoming_dest)
4304 /* We aren't entering the loop at the top. Since we've established
4305 that the loop is entered only at one point, this means there
4306 can't be fallthru edges into the head. Any such fallthru edges
4307 would become invalid when we insert the new block, so verify
4308 that this does not in fact happen. */
4309 FOR_EACH_EDGE (e, ei, loop->head->preds)
4310 gcc_assert (!(e->flags & EDGE_FALLTHRU));
4314 emit_insn_before (seq, BB_HEAD (loop->head));
4315 seq = emit_label_before (gen_label_rtx (), seq);
4317 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
4318 FOR_EACH_EDGE (e, ei, loop->incoming)
4320 if (!(e->flags & EDGE_FALLTHRU)
4321 || e->dest != loop->head)
4322 redirect_edge_and_branch_force (e, new_bb);
4324 redirect_edge_succ (e, new_bb);
4326 e = make_edge (new_bb, loop->head, 0);
4329 delete_insn (loop->loop_end);
4330 /* Insert the loop end label before the last instruction of the loop. */
4331 emit_label_before (loop->end_label, loop->last_insn);
4338 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
4342 if (DPREG_P (loop->iter_reg))
4344 /* If loop->iter_reg is a DREG or PREG, we can split it here
4345 without scratch register. */
4348 emit_insn_before (gen_addsi3 (loop->iter_reg,
4353 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
4354 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
4355 loop->iter_reg, const0_rtx,
4359 JUMP_LABEL (insn) = loop->start_label;
4360 LABEL_NUSES (loop->start_label)++;
4361 delete_insn (loop->loop_end);
4365 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
4366 a newly set up structure describing the loop, it is this function's
4367 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
4368 loop_end insn and its enclosing basic block. */
4371 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
4375 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
4377 loop->tail = tail_bb;
4378 loop->head = BRANCH_EDGE (tail_bb)->dest;
4379 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
4380 loop->loop_end = tail_insn;
4381 loop->last_insn = NULL_RTX;
4382 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
4383 loop->depth = loop->length = 0;
4385 loop->clobber_loop0 = loop->clobber_loop1 = 0;
4388 loop->incoming = VEC_alloc (edge, gc, 2);
4389 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
4390 loop->end_label = NULL_RTX;
4393 VEC_safe_push (basic_block, heap, works, loop->head);
4395 while (VEC_iterate (basic_block, works, dwork++, bb))
4399 if (bb == EXIT_BLOCK_PTR)
4401 /* We've reached the exit block. The loop must be bad. */
4404 ";; Loop is bad - reached exit block while scanning\n");
4409 if (!bitmap_set_bit (loop->block_bitmap, bb->index))
4412 /* We've not seen this block before. Add it to the loop's
4413 list and then add each successor to the work list. */
4415 VEC_safe_push (basic_block, heap, loop->blocks, bb);
4419 FOR_EACH_EDGE (e, ei, bb->succs)
4421 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
4422 if (!REGNO_REG_SET_P (df_get_live_in (succ),
4423 REGNO (loop->iter_reg)))
4425 if (!VEC_space (basic_block, works, 1))
4429 VEC_block_remove (basic_block, works, 0, dwork);
4433 VEC_reserve (basic_block, heap, works, 1);
4435 VEC_quick_push (basic_block, works, succ);
4440 /* Find the predecessor, and make sure nothing else jumps into this loop. */
4444 FOR_EACH_VEC_ELT (basic_block, loop->blocks, dwork, bb)
4448 FOR_EACH_EDGE (e, ei, bb->preds)
4450 basic_block pred = e->src;
4452 if (!bfin_bb_in_loop (loop, pred))
4455 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
4456 loop->loop_no, pred->index,
4458 VEC_safe_push (edge, gc, loop->incoming, e);
4463 for (pass = 0, retry = 1; retry && pass < 2; pass++)
4470 FOR_EACH_EDGE (e, ei, loop->incoming)
4474 loop->incoming_src = e->src;
4475 loop->incoming_dest = e->dest;
4480 if (e->dest != loop->incoming_dest)
4481 loop->incoming_dest = NULL;
4482 if (e->src != loop->incoming_src)
4483 loop->incoming_src = NULL;
4485 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
4491 ";; retrying loop %d with forwarder blocks\n",
4499 ";; can't find suitable entry for loop %d\n",
4507 FOR_EACH_EDGE (e, ei, loop->incoming)
4509 if (forwarder_block_p (e->src))
4516 ";; Adding forwarder block %d to loop %d and retrying\n",
4517 e->src->index, loop->loop_no);
4518 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
4519 bitmap_set_bit (loop->block_bitmap, e->src->index);
4520 FOR_EACH_EDGE (e2, ei2, e->src->preds)
4521 VEC_safe_push (edge, gc, loop->incoming, e2);
4522 VEC_unordered_remove (edge, loop->incoming, ei.index);
4530 fprintf (dump_file, ";; No forwarder blocks found\n");
4538 VEC_free (basic_block, heap, works);
4541 /* Analyze the structure of the loops in the current function. Use STACK
4542 for bitmap allocations. Returns all the valid candidates for hardware
4543 loops found in this function. */
4545 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
4547 loop_info loops = NULL;
4553 /* Find all the possible loop tails. This means searching for every
4554 loop_end instruction. For each one found, create a loop_info
4555 structure and add the head block to the work list. */
4558 rtx tail = BB_END (bb);
4560 while (GET_CODE (tail) == NOTE)
4561 tail = PREV_INSN (tail);
4565 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
4568 /* A possible loop end */
4570 /* There's a degenerate case we can handle - an empty loop consisting
4571 of only a back branch. Handle that by deleting the branch. */
4572 insn = BB_HEAD (BRANCH_EDGE (bb)->dest);
4573 if (next_real_insn (insn) == tail)
4577 fprintf (dump_file, ";; degenerate loop ending at\n");
4578 print_rtl_single (dump_file, tail);
4580 delete_insn_and_edges (tail);
4584 loop = XNEW (struct loop_info_d);
4587 loop->loop_no = nloops++;
4588 loop->blocks = VEC_alloc (basic_block, heap, 20);
4589 loop->block_bitmap = BITMAP_ALLOC (stack);
4594 fprintf (dump_file, ";; potential loop %d ending at\n",
4596 print_rtl_single (dump_file, tail);
4599 bfin_discover_loop (loop, bb, tail);
4603 tmp_bitmap = BITMAP_ALLOC (stack);
4604 /* Compute loop nestings. */
4605 for (loop = loops; loop; loop = loop->next)
4611 for (other = loop->next; other; other = other->next)
4616 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
4617 if (bitmap_empty_p (tmp_bitmap))
4619 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
4621 other->outer = loop;
4622 VEC_safe_push (loop_info, heap, loop->loops, other);
4624 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
4626 loop->outer = other;
4627 VEC_safe_push (loop_info, heap, other->loops, loop);
4633 ";; can't find suitable nesting for loops %d and %d\n",
4634 loop->loop_no, other->loop_no);
4635 loop->bad = other->bad = 1;
4639 BITMAP_FREE (tmp_bitmap);
4644 /* Free up the loop structures in LOOPS. */
4646 free_loops (loop_info loops)
4650 loop_info loop = loops;
4652 VEC_free (loop_info, heap, loop->loops);
4653 VEC_free (basic_block, heap, loop->blocks);
4654 BITMAP_FREE (loop->block_bitmap);
4659 #define BB_AUX_INDEX(BB) ((intptr_t)(BB)->aux)
4661 /* The taken-branch edge from the loop end can actually go forward. Since the
4662 Blackfin's LSETUP instruction requires that the loop end be after the loop
4663 start, try to reorder a loop's basic blocks when we find such a case. */
4665 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4672 cfg_layout_initialize (0);
4674 for (loop = loops; loop; loop = loop->next)
4684 /* Recreate an index for basic blocks that represents their order. */
4685 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4686 bb != EXIT_BLOCK_PTR;
4687 bb = bb->next_bb, index++)
4688 bb->aux = (PTR) index;
4690 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4693 FOR_EACH_EDGE (e, ei, loop->head->succs)
4695 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4696 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4698 basic_block start_bb = e->dest;
4699 basic_block start_prev_bb = start_bb->prev_bb;
4702 fprintf (dump_file, ";; Moving block %d before block %d\n",
4703 loop->head->index, start_bb->index);
4704 loop->head->prev_bb->next_bb = loop->head->next_bb;
4705 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4707 loop->head->prev_bb = start_prev_bb;
4708 loop->head->next_bb = start_bb;
4709 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4713 loops = loops->next;
4718 if (bb->next_bb != EXIT_BLOCK_PTR)
4719 bb->aux = bb->next_bb;
4723 cfg_layout_finalize ();
4727 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4728 and tries to rewrite the RTL of these loops so that proper Blackfin
4729 hardware loops are generated. */
4732 bfin_reorg_loops (FILE *dump_file)
4734 loop_info loops = NULL;
4737 bitmap_obstack stack;
4739 bitmap_obstack_initialize (&stack);
4742 fprintf (dump_file, ";; Find loops, first pass\n\n");
4744 loops = bfin_discover_loops (&stack, dump_file);
4747 bfin_dump_loops (loops);
4749 bfin_reorder_loops (loops, dump_file);
4753 fprintf (dump_file, ";; Find loops, second pass\n\n");
4755 loops = bfin_discover_loops (&stack, dump_file);
4758 fprintf (dump_file, ";; All loops found:\n\n");
4759 bfin_dump_loops (loops);
4762 /* Now apply the optimizations. */
4763 for (loop = loops; loop; loop = loop->next)
4764 bfin_optimize_loop (loop);
4768 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4769 bfin_dump_loops (loops);
4775 print_rtl (dump_file, get_insns ());
4780 splitting_loops = 1;
4783 rtx insn = BB_END (bb);
4787 try_split (PATTERN (insn), insn, 1);
4789 splitting_loops = 0;
4792 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4793 Returns true if we modified the insn chain, false otherwise. */
4795 gen_one_bundle (rtx slot[3])
4797 gcc_assert (slot[1] != NULL_RTX);
4799 /* Don't add extra NOPs if optimizing for size. */
4801 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
4804 /* Verify that we really can do the multi-issue. */
4807 rtx t = NEXT_INSN (slot[0]);
4808 while (t != slot[1])
4810 if (GET_CODE (t) != NOTE
4811 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4818 rtx t = NEXT_INSN (slot[1]);
4819 while (t != slot[2])
4821 if (GET_CODE (t) != NOTE
4822 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4828 if (slot[0] == NULL_RTX)
4830 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4831 df_insn_rescan (slot[0]);
4833 if (slot[2] == NULL_RTX)
4835 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4836 df_insn_rescan (slot[2]);
4839 /* Avoid line number information being printed inside one bundle. */
4840 if (INSN_LOCATOR (slot[1])
4841 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4842 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4843 if (INSN_LOCATOR (slot[2])
4844 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4845 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4847 /* Terminate them with "|| " instead of ";" in the output. */
4848 PUT_MODE (slot[0], SImode);
4849 PUT_MODE (slot[1], SImode);
4850 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4851 PUT_MODE (slot[2], QImode);
4855 /* Go through all insns, and use the information generated during scheduling
4856 to generate SEQUENCEs to represent bundles of instructions issued
4860 bfin_gen_bundles (void)
4869 slot[0] = slot[1] = slot[2] = NULL_RTX;
4870 for (insn = BB_HEAD (bb);; insn = next)
4873 rtx delete_this = NULL_RTX;
4875 if (NONDEBUG_INSN_P (insn))
4877 enum attr_type type = get_attr_type (insn);
4879 if (type == TYPE_STALL)
4881 gcc_assert (n_filled == 0);
4886 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
4888 else if (slot[1] == NULL_RTX)
4896 next = NEXT_INSN (insn);
4897 while (next && insn != BB_END (bb)
4899 && GET_CODE (PATTERN (next)) != USE
4900 && GET_CODE (PATTERN (next)) != CLOBBER))
4903 next = NEXT_INSN (insn);
4906 /* BB_END can change due to emitting extra NOPs, so check here. */
4907 at_end = insn == BB_END (bb);
4908 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4911 || !gen_one_bundle (slot))
4912 && slot[0] != NULL_RTX)
4914 rtx pat = PATTERN (slot[0]);
4915 if (GET_CODE (pat) == SET
4916 && GET_CODE (SET_SRC (pat)) == UNSPEC
4917 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4919 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4920 INSN_CODE (slot[0]) = -1;
4921 df_insn_rescan (slot[0]);
4925 slot[0] = slot[1] = slot[2] = NULL_RTX;
4927 if (delete_this != NULL_RTX)
4928 delete_insn (delete_this);
4935 /* Ensure that no var tracking notes are emitted in the middle of a
4936 three-instruction bundle. */
4939 reorder_var_tracking_notes (void)
4945 rtx queue = NULL_RTX;
4946 bool in_bundle = false;
4948 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4950 next = NEXT_INSN (insn);
4954 /* Emit queued up notes at the last instruction of a bundle. */
4955 if (GET_MODE (insn) == QImode)
4959 rtx next_queue = PREV_INSN (queue);
4960 PREV_INSN (NEXT_INSN (insn)) = queue;
4961 NEXT_INSN (queue) = NEXT_INSN (insn);
4962 NEXT_INSN (insn) = queue;
4963 PREV_INSN (queue) = insn;
4968 else if (GET_MODE (insn) == SImode)
4971 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4975 rtx prev = PREV_INSN (insn);
4976 PREV_INSN (next) = prev;
4977 NEXT_INSN (prev) = next;
4979 PREV_INSN (insn) = queue;
4987 /* On some silicon revisions, functions shorter than a certain number of cycles
4988 can cause unpredictable behaviour. Work around this by adding NOPs as
4991 workaround_rts_anomaly (void)
4993 rtx insn, first_insn = NULL_RTX;
4996 if (! ENABLE_WA_RETS)
4999 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5003 if (BARRIER_P (insn))
5006 if (NOTE_P (insn) || LABEL_P (insn))
5009 if (first_insn == NULL_RTX)
5011 pat = PATTERN (insn);
5012 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5013 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5014 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5022 if (recog_memoized (insn) == CODE_FOR_return_internal)
5025 /* Nothing to worry about for direct jumps. */
5026 if (!any_condjump_p (insn))
5032 else if (INSN_P (insn))
5034 rtx pat = PATTERN (insn);
5035 int this_cycles = 1;
5037 if (GET_CODE (pat) == PARALLEL)
5039 if (push_multiple_operation (pat, VOIDmode)
5040 || pop_multiple_operation (pat, VOIDmode))
5041 this_cycles = n_regs_to_save;
5045 int icode = recog_memoized (insn);
5047 if (icode == CODE_FOR_link)
5049 else if (icode == CODE_FOR_unlink)
5051 else if (icode == CODE_FOR_mulsi3)
5054 if (this_cycles >= cycles)
5057 cycles -= this_cycles;
5062 emit_insn_before (gen_nop (), first_insn);
5067 /* Return an insn type for INSN that can be used by the caller for anomaly
5068 workarounds. This differs from plain get_attr_type in that it handles
5071 static enum attr_type
5072 type_for_anomaly (rtx insn)
5074 rtx pat = PATTERN (insn);
5075 if (GET_CODE (pat) == SEQUENCE)
5078 t = get_attr_type (XVECEXP (pat, 0, 1));
5081 t = get_attr_type (XVECEXP (pat, 0, 2));
5087 return get_attr_type (insn);
5090 /* Return true iff the address found in MEM is based on the register
5091 NP_REG and optionally has a positive offset. */
5093 harmless_null_pointer_p (rtx mem, int np_reg)
5095 mem = XEXP (mem, 0);
5096 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
5097 mem = XEXP (mem, 0);
5098 if (REG_P (mem) && (int) REGNO (mem) == np_reg)
5100 if (GET_CODE (mem) == PLUS
5101 && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg)
5103 mem = XEXP (mem, 1);
5104 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
5110 /* Return nonzero if INSN contains any loads that may trap. */
5113 trapping_loads_p (rtx insn, int np_reg, bool after_np_branch)
5115 rtx mem = SET_SRC (single_set (insn));
5117 if (!after_np_branch)
5119 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
5120 && may_trap_p (mem));
5123 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
5124 a three-insn bundle, see if one of them is a load and return that if so.
5125 Return NULL_RTX if the insn does not contain loads. */
5127 find_load (rtx insn)
5129 if (!NONDEBUG_INSN_P (insn))
5131 if (get_attr_type (insn) == TYPE_MCLD)
5133 if (GET_MODE (insn) != SImode)
5136 insn = NEXT_INSN (insn);
5137 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
5138 && get_attr_type (insn) == TYPE_MCLD)
5140 } while (GET_MODE (insn) != QImode);
5144 /* Determine whether PAT is an indirect call pattern. */
5146 indirect_call_p (rtx pat)
5148 if (GET_CODE (pat) == PARALLEL)
5149 pat = XVECEXP (pat, 0, 0);
5150 if (GET_CODE (pat) == SET)
5151 pat = SET_SRC (pat);
5152 gcc_assert (GET_CODE (pat) == CALL);
5153 pat = XEXP (pat, 0);
5154 gcc_assert (GET_CODE (pat) == MEM);
5155 pat = XEXP (pat, 0);
5160 /* During workaround_speculation, track whether we're in the shadow of a
5161 conditional branch that tests a P register for NULL. If so, we can omit
5162 emitting NOPs if we see a load from that P register, since a speculative
5163 access at address 0 isn't a problem, and the load is executed in all other
5165 Global for communication with note_np_check_stores through note_stores.
5167 int np_check_regno = -1;
5168 bool np_after_branch = false;
5170 /* Subroutine of workaround_speculation, called through note_stores. */
5172 note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
5173 void *data ATTRIBUTE_UNUSED)
5175 if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
5176 np_check_regno = -1;
5180 workaround_speculation (void)
5183 rtx last_condjump = NULL_RTX;
5184 int cycles_since_jump = INT_MAX;
5185 int delay_added = 0;
5187 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5188 && ! ENABLE_WA_INDIRECT_CALLS)
5191 /* First pass: find predicted-false branches; if something after them
5192 needs nops, insert them or change the branch to predict true. */
5193 for (insn = get_insns (); insn; insn = next)
5196 int delay_needed = 0;
5198 next = find_next_insn_start (insn);
5200 if (NOTE_P (insn) || BARRIER_P (insn))
5205 np_check_regno = -1;
5209 pat = PATTERN (insn);
5210 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5211 || GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
5214 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
5216 np_check_regno = -1;
5222 /* Is this a condjump based on a null pointer comparison we saw
5224 if (np_check_regno != -1
5225 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
5227 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
5228 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
5229 if (GET_CODE (op) == NE)
5230 np_after_branch = true;
5232 if (any_condjump_p (insn)
5233 && ! cbranch_predicted_taken_p (insn))
5235 last_condjump = insn;
5237 cycles_since_jump = 0;
5240 cycles_since_jump = INT_MAX;
5242 else if (CALL_P (insn))
5244 np_check_regno = -1;
5245 if (cycles_since_jump < INT_MAX)
5246 cycles_since_jump++;
5247 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
5252 else if (NONDEBUG_INSN_P (insn))
5254 rtx load_insn = find_load (insn);
5255 enum attr_type type = type_for_anomaly (insn);
5257 if (cycles_since_jump < INT_MAX)
5258 cycles_since_jump++;
5260 /* Detect a comparison of a P register with zero. If we later
5261 see a condjump based on it, we have found a null pointer
5263 if (recog_memoized (insn) == CODE_FOR_compare_eq)
5265 rtx src = SET_SRC (PATTERN (insn));
5266 if (REG_P (XEXP (src, 0))
5267 && P_REGNO_P (REGNO (XEXP (src, 0)))
5268 && XEXP (src, 1) == const0_rtx)
5270 np_check_regno = REGNO (XEXP (src, 0));
5271 np_after_branch = false;
5274 np_check_regno = -1;
5277 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5279 if (trapping_loads_p (load_insn, np_check_regno,
5283 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5286 /* See if we need to forget about a null pointer comparison
5287 we found earlier. */
5288 if (recog_memoized (insn) != CODE_FOR_compare_eq)
5290 note_stores (PATTERN (insn), note_np_check_stores, NULL);
5291 if (np_check_regno != -1)
5293 if (find_regno_note (insn, REG_INC, np_check_regno))
5294 np_check_regno = -1;
5300 if (delay_needed > cycles_since_jump
5301 && (delay_needed - cycles_since_jump) > delay_added)
5305 rtx *op = recog_data.operand;
5307 delay_needed -= cycles_since_jump;
5309 extract_insn (last_condjump);
5312 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
5314 cycles_since_jump = INT_MAX;
5318 /* Do not adjust cycles_since_jump in this case, so that
5319 we'll increase the number of NOPs for a subsequent insn
5321 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
5322 GEN_INT (delay_needed));
5323 delay_added = delay_needed;
5325 PATTERN (last_condjump) = pat1;
5326 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
5330 cycles_since_jump = INT_MAX;
5335 /* Second pass: for predicted-true branches, see if anything at the
5336 branch destination needs extra nops. */
5337 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5339 int cycles_since_jump;
5341 && any_condjump_p (insn)
5342 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
5343 || cbranch_predicted_taken_p (insn)))
5345 rtx target = JUMP_LABEL (insn);
5349 cycles_since_jump = 0;
5350 for (; target && cycles_since_jump < 3; target = next_tgt)
5354 next_tgt = find_next_insn_start (target);
5356 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
5359 pat = PATTERN (target);
5360 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5361 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5362 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5365 if (NONDEBUG_INSN_P (target))
5367 rtx load_insn = find_load (target);
5368 enum attr_type type = type_for_anomaly (target);
5369 int delay_needed = 0;
5370 if (cycles_since_jump < INT_MAX)
5371 cycles_since_jump++;
5373 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5375 if (trapping_loads_p (load_insn, -1, false))
5378 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5381 if (delay_needed > cycles_since_jump)
5383 rtx prev = prev_real_insn (label);
5384 delay_needed -= cycles_since_jump;
5386 fprintf (dump_file, "Adding %d nops after %d\n",
5387 delay_needed, INSN_UID (label));
5389 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
5396 "Reducing nops on insn %d.\n",
5399 x = XVECEXP (x, 0, 1);
5400 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
5401 XVECEXP (x, 0, 0) = GEN_INT (v);
5403 while (delay_needed-- > 0)
5404 emit_insn_after (gen_nop (), label);
5413 /* Called just before the final scheduling pass. If we need to insert NOPs
5414 later on to work around speculative loads, insert special placeholder
5415 insns that cause loads to be delayed for as many cycles as necessary
5416 (and possible). This reduces the number of NOPs we need to add.
5417 The dummy insns we generate are later removed by bfin_gen_bundles. */
5419 add_sched_insns_for_speculation (void)
5423 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5424 && ! ENABLE_WA_INDIRECT_CALLS)
5427 /* First pass: find predicted-false branches; if something after them
5428 needs nops, insert them or change the branch to predict true. */
5429 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5433 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
5436 pat = PATTERN (insn);
5437 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5438 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5439 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5444 if (any_condjump_p (insn)
5445 && !cbranch_predicted_taken_p (insn))
5447 rtx n = next_real_insn (insn);
5448 emit_insn_before (gen_stall (GEN_INT (3)), n);
5453 /* Second pass: for predicted-true branches, see if anything at the
5454 branch destination needs extra nops. */
5455 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5458 && any_condjump_p (insn)
5459 && (cbranch_predicted_taken_p (insn)))
5461 rtx target = JUMP_LABEL (insn);
5462 rtx next = next_real_insn (target);
5464 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
5465 && get_attr_type (next) == TYPE_STALL)
5467 emit_insn_before (gen_stall (GEN_INT (1)), next);
5472 /* We use the machine specific reorg pass for emitting CSYNC instructions
5473 after conditional branches as needed.
5475 The Blackfin is unusual in that a code sequence like
5478 may speculatively perform the load even if the condition isn't true. This
5479 happens for a branch that is predicted not taken, because the pipeline
5480 isn't flushed or stalled, so the early stages of the following instructions,
5481 which perform the memory reference, are allowed to execute before the
5482 jump condition is evaluated.
5483 Therefore, we must insert additional instructions in all places where this
5484 could lead to incorrect behavior. The manual recommends CSYNC, while
5485 VDSP seems to use NOPs (even though its corresponding compiler option is
5488 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
5489 When optimizing for size, we turn the branch into a predicted taken one.
5490 This may be slower due to mispredicts, but saves code size. */
5495 /* We are freeing block_for_insn in the toplev to keep compatibility
5496 with old MDEP_REORGS that are not CFG based. Recompute it now. */
5497 compute_bb_for_insn ();
5499 if (bfin_flag_schedule_insns2)
5501 splitting_for_sched = 1;
5503 splitting_for_sched = 0;
5505 add_sched_insns_for_speculation ();
5507 timevar_push (TV_SCHED2);
5508 if (flag_selective_scheduling2
5509 && !maybe_skip_selective_scheduling ())
5510 run_selective_scheduling ();
5513 timevar_pop (TV_SCHED2);
5515 /* Examine the schedule and insert nops as necessary for 64-bit parallel
5517 bfin_gen_bundles ();
5522 /* Doloop optimization */
5523 if (cfun->machine->has_hardware_loops)
5524 bfin_reorg_loops (dump_file);
5526 workaround_speculation ();
5528 if (bfin_flag_var_tracking)
5530 timevar_push (TV_VAR_TRACKING);
5531 variable_tracking_main ();
5532 reorder_var_tracking_notes ();
5533 timevar_pop (TV_VAR_TRACKING);
5536 df_finish_pass (false);
5538 workaround_rts_anomaly ();
5541 /* Handle interrupt_handler, exception_handler and nmi_handler function
5542 attributes; arguments as in struct attribute_spec.handler. */
5545 handle_int_attribute (tree *node, tree name,
5546 tree args ATTRIBUTE_UNUSED,
5547 int flags ATTRIBUTE_UNUSED,
5551 if (TREE_CODE (x) == FUNCTION_DECL)
5554 if (TREE_CODE (x) != FUNCTION_TYPE)
5556 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5558 *no_add_attrs = true;
5560 else if (funkind (x) != SUBROUTINE)
5561 error ("multiple function type attributes specified");
5566 /* Return 0 if the attributes for two types are incompatible, 1 if they
5567 are compatible, and 2 if they are nearly compatible (which causes a
5568 warning to be generated). */
5571 bfin_comp_type_attributes (const_tree type1, const_tree type2)
5573 e_funkind kind1, kind2;
5575 if (TREE_CODE (type1) != FUNCTION_TYPE)
5578 kind1 = funkind (type1);
5579 kind2 = funkind (type2);
5584 /* Check for mismatched modifiers */
5585 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
5586 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
5589 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
5590 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
5593 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
5594 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
5597 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
5598 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
5604 /* Handle a "longcall" or "shortcall" attribute; arguments as in
5605 struct attribute_spec.handler. */
5608 bfin_handle_longcall_attribute (tree *node, tree name,
5609 tree args ATTRIBUTE_UNUSED,
5610 int flags ATTRIBUTE_UNUSED,
5613 if (TREE_CODE (*node) != FUNCTION_TYPE
5614 && TREE_CODE (*node) != FIELD_DECL
5615 && TREE_CODE (*node) != TYPE_DECL)
5617 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5619 *no_add_attrs = true;
5622 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
5623 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
5624 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
5625 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
5627 warning (OPT_Wattributes,
5628 "can%'t apply both longcall and shortcall attributes to the same function");
5629 *no_add_attrs = true;
5635 /* Handle a "l1_text" attribute; arguments as in
5636 struct attribute_spec.handler. */
5639 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5640 int ARG_UNUSED (flags), bool *no_add_attrs)
5644 if (TREE_CODE (decl) != FUNCTION_DECL)
5646 error ("%qE attribute only applies to functions",
5648 *no_add_attrs = true;
5651 /* The decl may have already been given a section attribute
5652 from a previous declaration. Ensure they match. */
5653 else if (DECL_SECTION_NAME (decl) != NULL_TREE
5654 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5657 error ("section of %q+D conflicts with previous declaration",
5659 *no_add_attrs = true;
5662 DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
5667 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
5668 arguments as in struct attribute_spec.handler. */
5671 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5672 int ARG_UNUSED (flags), bool *no_add_attrs)
5676 if (TREE_CODE (decl) != VAR_DECL)
5678 error ("%qE attribute only applies to variables",
5680 *no_add_attrs = true;
5682 else if (current_function_decl != NULL_TREE
5683 && !TREE_STATIC (decl))
5685 error ("%qE attribute cannot be specified for local variables",
5687 *no_add_attrs = true;
5691 const char *section_name;
5693 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
5694 section_name = ".l1.data";
5695 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
5696 section_name = ".l1.data.A";
5697 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
5698 section_name = ".l1.data.B";
5702 /* The decl may have already been given a section attribute
5703 from a previous declaration. Ensure they match. */
5704 if (DECL_SECTION_NAME (decl) != NULL_TREE
5705 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5708 error ("section of %q+D conflicts with previous declaration",
5710 *no_add_attrs = true;
5713 DECL_SECTION_NAME (decl)
5714 = build_string (strlen (section_name) + 1, section_name);
5720 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
5723 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
5724 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
5729 if (TREE_CODE (decl) == FUNCTION_DECL)
5731 if (DECL_SECTION_NAME (decl) != NULL_TREE
5732 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5735 error ("section of %q+D conflicts with previous declaration",
5737 *no_add_attrs = true;
5740 DECL_SECTION_NAME (decl) = build_string (9, ".l2.text");
5742 else if (TREE_CODE (decl) == VAR_DECL)
5744 if (DECL_SECTION_NAME (decl) != NULL_TREE
5745 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5748 error ("section of %q+D conflicts with previous declaration",
5750 *no_add_attrs = true;
5753 DECL_SECTION_NAME (decl) = build_string (9, ".l2.data");
5759 /* Table of valid machine attributes. */
5760 static const struct attribute_spec bfin_attribute_table[] =
5762 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
5763 affects_type_identity } */
5764 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
5766 { "exception_handler", 0, 0, false, true, true, handle_int_attribute,
5768 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false },
5769 { "nesting", 0, 0, false, true, true, NULL, false },
5770 { "kspisusp", 0, 0, false, true, true, NULL, false },
5771 { "saveall", 0, 0, false, true, true, NULL, false },
5772 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
5774 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
5776 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
5778 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
5780 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
5782 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
5784 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false },
5785 { NULL, 0, 0, false, false, false, NULL, false }
5788 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
5789 tell the assembler to generate pointers to function descriptors in
5793 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
5795 if (TARGET_FDPIC && size == UNITS_PER_WORD)
5797 if (GET_CODE (value) == SYMBOL_REF
5798 && SYMBOL_REF_FUNCTION_P (value))
5800 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
5801 output_addr_const (asm_out_file, value);
5802 fputs (")\n", asm_out_file);
5807 /* We've set the unaligned SI op to NULL, so we always have to
5808 handle the unaligned case here. */
5809 assemble_integer_with_op ("\t.4byte\t", value);
5813 return default_assemble_integer (value, size, aligned_p);
5816 /* Output the assembler code for a thunk function. THUNK_DECL is the
5817 declaration for the thunk function itself, FUNCTION is the decl for
5818 the target function. DELTA is an immediate constant offset to be
5819 added to THIS. If VCALL_OFFSET is nonzero, the word at
5820 *(*this + vcall_offset) should be added to THIS. */
5823 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
5824 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
5825 HOST_WIDE_INT vcall_offset, tree function)
5828 /* The this parameter is passed as the first argument. */
5829 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
5831 /* Adjust the this parameter by a fixed constant. */
5835 if (delta >= -64 && delta <= 63)
5837 xops[0] = GEN_INT (delta);
5838 output_asm_insn ("%1 += %0;", xops);
5840 else if (delta >= -128 && delta < -64)
5842 xops[0] = GEN_INT (delta + 64);
5843 output_asm_insn ("%1 += -64; %1 += %0;", xops);
5845 else if (delta > 63 && delta <= 126)
5847 xops[0] = GEN_INT (delta - 63);
5848 output_asm_insn ("%1 += 63; %1 += %0;", xops);
5852 xops[0] = GEN_INT (delta);
5853 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5857 /* Adjust the this parameter by a value stored in the vtable. */
5860 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5861 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5865 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5867 /* Adjust the this parameter. */
5868 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
5869 if (!memory_operand (xops[0], Pmode))
5871 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5872 xops[0] = GEN_INT (vcall_offset);
5874 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5875 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5878 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5881 xops[0] = XEXP (DECL_RTL (function), 0);
5882 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5883 output_asm_insn ("jump.l\t%P0", xops);
5886 /* Codes for all the Blackfin builtins. */
5892 BFIN_BUILTIN_COMPOSE_2X16,
5893 BFIN_BUILTIN_EXTRACTLO,
5894 BFIN_BUILTIN_EXTRACTHI,
5896 BFIN_BUILTIN_SSADD_2X16,
5897 BFIN_BUILTIN_SSSUB_2X16,
5898 BFIN_BUILTIN_SSADDSUB_2X16,
5899 BFIN_BUILTIN_SSSUBADD_2X16,
5900 BFIN_BUILTIN_MULT_2X16,
5901 BFIN_BUILTIN_MULTR_2X16,
5902 BFIN_BUILTIN_NEG_2X16,
5903 BFIN_BUILTIN_ABS_2X16,
5904 BFIN_BUILTIN_MIN_2X16,
5905 BFIN_BUILTIN_MAX_2X16,
5907 BFIN_BUILTIN_SSADD_1X16,
5908 BFIN_BUILTIN_SSSUB_1X16,
5909 BFIN_BUILTIN_MULT_1X16,
5910 BFIN_BUILTIN_MULTR_1X16,
5911 BFIN_BUILTIN_NORM_1X16,
5912 BFIN_BUILTIN_NEG_1X16,
5913 BFIN_BUILTIN_ABS_1X16,
5914 BFIN_BUILTIN_MIN_1X16,
5915 BFIN_BUILTIN_MAX_1X16,
5917 BFIN_BUILTIN_SUM_2X16,
5918 BFIN_BUILTIN_DIFFHL_2X16,
5919 BFIN_BUILTIN_DIFFLH_2X16,
5921 BFIN_BUILTIN_SSADD_1X32,
5922 BFIN_BUILTIN_SSSUB_1X32,
5923 BFIN_BUILTIN_NORM_1X32,
5924 BFIN_BUILTIN_ROUND_1X32,
5925 BFIN_BUILTIN_NEG_1X32,
5926 BFIN_BUILTIN_ABS_1X32,
5927 BFIN_BUILTIN_MIN_1X32,
5928 BFIN_BUILTIN_MAX_1X32,
5929 BFIN_BUILTIN_MULT_1X32,
5930 BFIN_BUILTIN_MULT_1X32X32,
5931 BFIN_BUILTIN_MULT_1X32X32NS,
5933 BFIN_BUILTIN_MULHISILL,
5934 BFIN_BUILTIN_MULHISILH,
5935 BFIN_BUILTIN_MULHISIHL,
5936 BFIN_BUILTIN_MULHISIHH,
5938 BFIN_BUILTIN_LSHIFT_1X16,
5939 BFIN_BUILTIN_LSHIFT_2X16,
5940 BFIN_BUILTIN_SSASHIFT_1X16,
5941 BFIN_BUILTIN_SSASHIFT_2X16,
5942 BFIN_BUILTIN_SSASHIFT_1X32,
5944 BFIN_BUILTIN_CPLX_MUL_16,
5945 BFIN_BUILTIN_CPLX_MAC_16,
5946 BFIN_BUILTIN_CPLX_MSU_16,
5948 BFIN_BUILTIN_CPLX_MUL_16_S40,
5949 BFIN_BUILTIN_CPLX_MAC_16_S40,
5950 BFIN_BUILTIN_CPLX_MSU_16_S40,
5952 BFIN_BUILTIN_CPLX_SQU,
5954 BFIN_BUILTIN_LOADBYTES,
5959 #define def_builtin(NAME, TYPE, CODE) \
5961 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5965 /* Set up all builtin functions for this target. */
5967 bfin_init_builtins (void)
5969 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5970 tree void_ftype_void
5971 = build_function_type (void_type_node, void_list_node);
5972 tree short_ftype_short
5973 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5975 tree short_ftype_int_int
5976 = build_function_type_list (short_integer_type_node, integer_type_node,
5977 integer_type_node, NULL_TREE);
5978 tree int_ftype_int_int
5979 = build_function_type_list (integer_type_node, integer_type_node,
5980 integer_type_node, NULL_TREE);
5982 = build_function_type_list (integer_type_node, integer_type_node,
5984 tree short_ftype_int
5985 = build_function_type_list (short_integer_type_node, integer_type_node,
5987 tree int_ftype_v2hi_v2hi
5988 = build_function_type_list (integer_type_node, V2HI_type_node,
5989 V2HI_type_node, NULL_TREE);
5990 tree v2hi_ftype_v2hi_v2hi
5991 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5992 V2HI_type_node, NULL_TREE);
5993 tree v2hi_ftype_v2hi_v2hi_v2hi
5994 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5995 V2HI_type_node, V2HI_type_node, NULL_TREE);
5996 tree v2hi_ftype_int_int
5997 = build_function_type_list (V2HI_type_node, integer_type_node,
5998 integer_type_node, NULL_TREE);
5999 tree v2hi_ftype_v2hi_int
6000 = build_function_type_list (V2HI_type_node, V2HI_type_node,
6001 integer_type_node, NULL_TREE);
6002 tree int_ftype_short_short
6003 = build_function_type_list (integer_type_node, short_integer_type_node,
6004 short_integer_type_node, NULL_TREE);
6005 tree v2hi_ftype_v2hi
6006 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
6007 tree short_ftype_v2hi
6008 = build_function_type_list (short_integer_type_node, V2HI_type_node,
6011 = build_function_type_list (integer_type_node,
6012 build_pointer_type (integer_type_node),
6015 /* Add the remaining MMX insns with somewhat more complicated types. */
6016 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
6017 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
6019 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
6021 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
6022 BFIN_BUILTIN_COMPOSE_2X16);
6023 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
6024 BFIN_BUILTIN_EXTRACTHI);
6025 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
6026 BFIN_BUILTIN_EXTRACTLO);
6028 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
6029 BFIN_BUILTIN_MIN_2X16);
6030 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
6031 BFIN_BUILTIN_MAX_2X16);
6033 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
6034 BFIN_BUILTIN_SSADD_2X16);
6035 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
6036 BFIN_BUILTIN_SSSUB_2X16);
6037 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
6038 BFIN_BUILTIN_SSADDSUB_2X16);
6039 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
6040 BFIN_BUILTIN_SSSUBADD_2X16);
6041 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
6042 BFIN_BUILTIN_MULT_2X16);
6043 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
6044 BFIN_BUILTIN_MULTR_2X16);
6045 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
6046 BFIN_BUILTIN_NEG_2X16);
6047 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
6048 BFIN_BUILTIN_ABS_2X16);
6050 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
6051 BFIN_BUILTIN_MIN_1X16);
6052 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
6053 BFIN_BUILTIN_MAX_1X16);
6055 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
6056 BFIN_BUILTIN_SSADD_1X16);
6057 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
6058 BFIN_BUILTIN_SSSUB_1X16);
6059 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
6060 BFIN_BUILTIN_MULT_1X16);
6061 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
6062 BFIN_BUILTIN_MULTR_1X16);
6063 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
6064 BFIN_BUILTIN_NEG_1X16);
6065 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
6066 BFIN_BUILTIN_ABS_1X16);
6067 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
6068 BFIN_BUILTIN_NORM_1X16);
6070 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
6071 BFIN_BUILTIN_SUM_2X16);
6072 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
6073 BFIN_BUILTIN_DIFFHL_2X16);
6074 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
6075 BFIN_BUILTIN_DIFFLH_2X16);
6077 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
6078 BFIN_BUILTIN_MULHISILL);
6079 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
6080 BFIN_BUILTIN_MULHISIHL);
6081 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
6082 BFIN_BUILTIN_MULHISILH);
6083 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
6084 BFIN_BUILTIN_MULHISIHH);
6086 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
6087 BFIN_BUILTIN_MIN_1X32);
6088 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
6089 BFIN_BUILTIN_MAX_1X32);
6091 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
6092 BFIN_BUILTIN_SSADD_1X32);
6093 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
6094 BFIN_BUILTIN_SSSUB_1X32);
6095 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
6096 BFIN_BUILTIN_NEG_1X32);
6097 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
6098 BFIN_BUILTIN_ABS_1X32);
6099 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
6100 BFIN_BUILTIN_NORM_1X32);
6101 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
6102 BFIN_BUILTIN_ROUND_1X32);
6103 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
6104 BFIN_BUILTIN_MULT_1X32);
6105 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
6106 BFIN_BUILTIN_MULT_1X32X32);
6107 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
6108 BFIN_BUILTIN_MULT_1X32X32NS);
6111 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
6112 BFIN_BUILTIN_SSASHIFT_1X16);
6113 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
6114 BFIN_BUILTIN_SSASHIFT_2X16);
6115 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
6116 BFIN_BUILTIN_LSHIFT_1X16);
6117 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
6118 BFIN_BUILTIN_LSHIFT_2X16);
6119 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
6120 BFIN_BUILTIN_SSASHIFT_1X32);
6122 /* Complex numbers. */
6123 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
6124 BFIN_BUILTIN_SSADD_2X16);
6125 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
6126 BFIN_BUILTIN_SSSUB_2X16);
6127 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
6128 BFIN_BUILTIN_CPLX_MUL_16);
6129 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
6130 BFIN_BUILTIN_CPLX_MAC_16);
6131 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
6132 BFIN_BUILTIN_CPLX_MSU_16);
6133 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
6134 BFIN_BUILTIN_CPLX_MUL_16_S40);
6135 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
6136 BFIN_BUILTIN_CPLX_MAC_16_S40);
6137 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
6138 BFIN_BUILTIN_CPLX_MSU_16_S40);
6139 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
6140 BFIN_BUILTIN_CPLX_SQU);
6142 /* "Unaligned" load. */
6143 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
6144 BFIN_BUILTIN_LOADBYTES);
6149 struct builtin_description
6151 const enum insn_code icode;
6152 const char *const name;
6153 const enum bfin_builtins code;
6157 static const struct builtin_description bdesc_2arg[] =
6159 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
6161 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
6162 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
6163 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
6164 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
6165 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
6167 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
6168 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
6169 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
6170 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
6172 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
6173 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
6174 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
6175 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
6177 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
6178 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
6179 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
6180 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
6181 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
6182 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
6184 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
6185 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
6186 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
6187 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
6188 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
6190 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
6191 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
6192 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
6193 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
6197 static const struct builtin_description bdesc_1arg[] =
6199 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
6201 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
6203 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
6204 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
6205 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
6207 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
6208 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
6209 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
6210 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
6212 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
6213 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
6214 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
6215 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
6218 /* Errors in the source file can cause expand_expr to return const0_rtx
6219 where we expect a vector. To avoid crashing, use one of the vector
6220 clear instructions. */
6222 safe_vector_operand (rtx x, enum machine_mode mode)
6224 if (x != const0_rtx)
6226 x = gen_reg_rtx (SImode);
6228 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
6229 return gen_lowpart (mode, x);
6232 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
6233 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
6236 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
6240 tree arg0 = CALL_EXPR_ARG (exp, 0);
6241 tree arg1 = CALL_EXPR_ARG (exp, 1);
6242 rtx op0 = expand_normal (arg0);
6243 rtx op1 = expand_normal (arg1);
6244 enum machine_mode op0mode = GET_MODE (op0);
6245 enum machine_mode op1mode = GET_MODE (op1);
6246 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6247 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6248 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
6250 if (VECTOR_MODE_P (mode0))
6251 op0 = safe_vector_operand (op0, mode0);
6252 if (VECTOR_MODE_P (mode1))
6253 op1 = safe_vector_operand (op1, mode1);
6256 || GET_MODE (target) != tmode
6257 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6258 target = gen_reg_rtx (tmode);
6260 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
6263 op0 = gen_lowpart (HImode, op0);
6265 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
6268 op1 = gen_lowpart (HImode, op1);
6270 /* In case the insn wants input operands in modes different from
6271 the result, abort. */
6272 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
6273 && (op1mode == mode1 || op1mode == VOIDmode));
6275 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6276 op0 = copy_to_mode_reg (mode0, op0);
6277 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6278 op1 = copy_to_mode_reg (mode1, op1);
6281 pat = GEN_FCN (icode) (target, op0, op1);
6283 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
6291 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
6294 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
6298 tree arg0 = CALL_EXPR_ARG (exp, 0);
6299 rtx op0 = expand_normal (arg0);
6300 enum machine_mode op0mode = GET_MODE (op0);
6301 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6302 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6305 || GET_MODE (target) != tmode
6306 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6307 target = gen_reg_rtx (tmode);
6309 if (VECTOR_MODE_P (mode0))
6310 op0 = safe_vector_operand (op0, mode0);
6312 if (op0mode == SImode && mode0 == HImode)
6315 op0 = gen_lowpart (HImode, op0);
6317 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
6319 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6320 op0 = copy_to_mode_reg (mode0, op0);
6322 pat = GEN_FCN (icode) (target, op0);
6329 /* Expand an expression EXP that calls a built-in function,
6330 with result going to TARGET if that's convenient
6331 (and in mode MODE if that's convenient).
6332 SUBTARGET may be used as the target for computing one of EXP's operands.
6333 IGNORE is nonzero if the value is to be ignored. */
6336 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6337 rtx subtarget ATTRIBUTE_UNUSED,
6338 enum machine_mode mode ATTRIBUTE_UNUSED,
6339 int ignore ATTRIBUTE_UNUSED)
6342 enum insn_code icode;
6343 const struct builtin_description *d;
6344 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6345 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6346 tree arg0, arg1, arg2;
6347 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
6348 enum machine_mode tmode, mode0;
6352 case BFIN_BUILTIN_CSYNC:
6353 emit_insn (gen_csync ());
6355 case BFIN_BUILTIN_SSYNC:
6356 emit_insn (gen_ssync ());
6359 case BFIN_BUILTIN_DIFFHL_2X16:
6360 case BFIN_BUILTIN_DIFFLH_2X16:
6361 case BFIN_BUILTIN_SUM_2X16:
6362 arg0 = CALL_EXPR_ARG (exp, 0);
6363 op0 = expand_normal (arg0);
6364 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
6365 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
6366 : CODE_FOR_ssaddhilov2hi3);
6367 tmode = insn_data[icode].operand[0].mode;
6368 mode0 = insn_data[icode].operand[1].mode;
6371 || GET_MODE (target) != tmode
6372 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6373 target = gen_reg_rtx (tmode);
6375 if (VECTOR_MODE_P (mode0))
6376 op0 = safe_vector_operand (op0, mode0);
6378 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6379 op0 = copy_to_mode_reg (mode0, op0);
6381 pat = GEN_FCN (icode) (target, op0, op0);
6387 case BFIN_BUILTIN_MULT_1X32X32:
6388 case BFIN_BUILTIN_MULT_1X32X32NS:
6389 arg0 = CALL_EXPR_ARG (exp, 0);
6390 arg1 = CALL_EXPR_ARG (exp, 1);
6391 op0 = expand_normal (arg0);
6392 op1 = expand_normal (arg1);
6394 || !register_operand (target, SImode))
6395 target = gen_reg_rtx (SImode);
6396 if (! register_operand (op0, SImode))
6397 op0 = copy_to_mode_reg (SImode, op0);
6398 if (! register_operand (op1, SImode))
6399 op1 = copy_to_mode_reg (SImode, op1);
6401 a1reg = gen_rtx_REG (PDImode, REG_A1);
6402 a0reg = gen_rtx_REG (PDImode, REG_A0);
6403 tmp1 = gen_lowpart (V2HImode, op0);
6404 tmp2 = gen_lowpart (V2HImode, op1);
6405 emit_insn (gen_flag_macinit1hi (a1reg,
6406 gen_lowpart (HImode, op0),
6407 gen_lowpart (HImode, op1),
6408 GEN_INT (MACFLAG_FU)));
6409 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
6411 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
6412 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
6413 const1_rtx, const1_rtx,
6414 const1_rtx, const0_rtx, a1reg,
6415 const0_rtx, GEN_INT (MACFLAG_NONE),
6416 GEN_INT (MACFLAG_M)));
6419 /* For saturating multiplication, there's exactly one special case
6420 to be handled: multiplying the smallest negative value with
6421 itself. Due to shift correction in fractional multiplies, this
6422 can overflow. Iff this happens, OP2 will contain 1, which, when
6423 added in 32 bits to the smallest negative, wraps to the largest
6424 positive, which is the result we want. */
6425 op2 = gen_reg_rtx (V2HImode);
6426 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
6427 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
6428 gen_lowpart (SImode, op2)));
6429 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
6430 const1_rtx, const1_rtx,
6431 const1_rtx, const0_rtx, a1reg,
6432 const0_rtx, GEN_INT (MACFLAG_NONE),
6433 GEN_INT (MACFLAG_M)));
6434 op2 = gen_reg_rtx (SImode);
6435 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
6437 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
6438 const1_rtx, const0_rtx,
6439 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
6440 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
6441 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
6442 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
6443 emit_insn (gen_addsi3 (target, target, op2));
6446 case BFIN_BUILTIN_CPLX_MUL_16:
6447 case BFIN_BUILTIN_CPLX_MUL_16_S40:
6448 arg0 = CALL_EXPR_ARG (exp, 0);
6449 arg1 = CALL_EXPR_ARG (exp, 1);
6450 op0 = expand_normal (arg0);
6451 op1 = expand_normal (arg1);
6452 accvec = gen_reg_rtx (V2PDImode);
6453 icode = CODE_FOR_flag_macv2hi_parts;
6454 tmode = insn_data[icode].operand[0].mode;
6457 || GET_MODE (target) != V2HImode
6458 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6459 target = gen_reg_rtx (tmode);
6460 if (! register_operand (op0, GET_MODE (op0)))
6461 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6462 if (! register_operand (op1, GET_MODE (op1)))
6463 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6465 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
6466 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6467 const0_rtx, const0_rtx,
6468 const1_rtx, GEN_INT (MACFLAG_W32)));
6470 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6471 const0_rtx, const0_rtx,
6472 const1_rtx, GEN_INT (MACFLAG_NONE)));
6473 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
6474 const1_rtx, const1_rtx,
6475 const0_rtx, accvec, const1_rtx, const0_rtx,
6476 GEN_INT (MACFLAG_NONE), accvec));
6480 case BFIN_BUILTIN_CPLX_MAC_16:
6481 case BFIN_BUILTIN_CPLX_MSU_16:
6482 case BFIN_BUILTIN_CPLX_MAC_16_S40:
6483 case BFIN_BUILTIN_CPLX_MSU_16_S40:
6484 arg0 = CALL_EXPR_ARG (exp, 0);
6485 arg1 = CALL_EXPR_ARG (exp, 1);
6486 arg2 = CALL_EXPR_ARG (exp, 2);
6487 op0 = expand_normal (arg0);
6488 op1 = expand_normal (arg1);
6489 op2 = expand_normal (arg2);
6490 accvec = gen_reg_rtx (V2PDImode);
6491 icode = CODE_FOR_flag_macv2hi_parts;
6492 tmode = insn_data[icode].operand[0].mode;
6495 || GET_MODE (target) != V2HImode
6496 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6497 target = gen_reg_rtx (tmode);
6498 if (! register_operand (op1, GET_MODE (op1)))
6499 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6500 if (! register_operand (op2, GET_MODE (op2)))
6501 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
6503 tmp1 = gen_reg_rtx (SImode);
6504 tmp2 = gen_reg_rtx (SImode);
6505 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
6506 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
6507 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
6508 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
6509 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6510 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
6511 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6512 const0_rtx, const0_rtx,
6513 const1_rtx, accvec, const0_rtx,
6515 GEN_INT (MACFLAG_W32)));
6517 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6518 const0_rtx, const0_rtx,
6519 const1_rtx, accvec, const0_rtx,
6521 GEN_INT (MACFLAG_NONE)));
6522 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6523 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
6533 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
6534 const1_rtx, const1_rtx,
6535 const0_rtx, accvec, tmp1, tmp2,
6536 GEN_INT (MACFLAG_NONE), accvec));
6540 case BFIN_BUILTIN_CPLX_SQU:
6541 arg0 = CALL_EXPR_ARG (exp, 0);
6542 op0 = expand_normal (arg0);
6543 accvec = gen_reg_rtx (V2PDImode);
6544 icode = CODE_FOR_flag_mulv2hi;
6545 tmp1 = gen_reg_rtx (V2HImode);
6546 tmp2 = gen_reg_rtx (V2HImode);
6549 || GET_MODE (target) != V2HImode
6550 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6551 target = gen_reg_rtx (V2HImode);
6552 if (! register_operand (op0, GET_MODE (op0)))
6553 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6555 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
6557 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
6558 const0_rtx, const1_rtx,
6559 GEN_INT (MACFLAG_NONE)));
6561 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
6563 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
6564 const0_rtx, const1_rtx));
6572 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6573 if (d->code == fcode)
6574 return bfin_expand_binop_builtin (d->icode, exp, target,
6577 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6578 if (d->code == fcode)
6579 return bfin_expand_unop_builtin (d->icode, exp, target);
6585 bfin_conditional_register_usage (void)
6587 /* initialize condition code flag register rtx */
6588 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
6589 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
6591 call_used_regs[FDPIC_REGNO] = 1;
6592 if (!TARGET_FDPIC && flag_pic)
6594 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
6595 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
6599 #undef TARGET_INIT_BUILTINS
6600 #define TARGET_INIT_BUILTINS bfin_init_builtins
6602 #undef TARGET_EXPAND_BUILTIN
6603 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
6605 #undef TARGET_ASM_GLOBALIZE_LABEL
6606 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
6608 #undef TARGET_ASM_FILE_START
6609 #define TARGET_ASM_FILE_START output_file_start
6611 #undef TARGET_ATTRIBUTE_TABLE
6612 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
6614 #undef TARGET_COMP_TYPE_ATTRIBUTES
6615 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
6617 #undef TARGET_RTX_COSTS
6618 #define TARGET_RTX_COSTS bfin_rtx_costs
6620 #undef TARGET_ADDRESS_COST
6621 #define TARGET_ADDRESS_COST bfin_address_cost
6623 #undef TARGET_ASM_INTEGER
6624 #define TARGET_ASM_INTEGER bfin_assemble_integer
6626 #undef TARGET_MACHINE_DEPENDENT_REORG
6627 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
6629 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6630 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
6632 #undef TARGET_ASM_OUTPUT_MI_THUNK
6633 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
6634 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6635 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
6637 #undef TARGET_SCHED_ADJUST_COST
6638 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
6640 #undef TARGET_SCHED_ISSUE_RATE
6641 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
6643 #undef TARGET_PROMOTE_FUNCTION_MODE
6644 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
6646 #undef TARGET_ARG_PARTIAL_BYTES
6647 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
6649 #undef TARGET_FUNCTION_ARG
6650 #define TARGET_FUNCTION_ARG bfin_function_arg
6652 #undef TARGET_FUNCTION_ARG_ADVANCE
6653 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
6655 #undef TARGET_PASS_BY_REFERENCE
6656 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
6658 #undef TARGET_SETUP_INCOMING_VARARGS
6659 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
6661 #undef TARGET_STRUCT_VALUE_RTX
6662 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
6664 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6665 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
6667 #undef TARGET_HANDLE_OPTION
6668 #define TARGET_HANDLE_OPTION bfin_handle_option
6670 #undef TARGET_OPTION_OVERRIDE
6671 #define TARGET_OPTION_OVERRIDE bfin_option_override
6673 #undef TARGET_DEFAULT_TARGET_FLAGS
6674 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
6676 #undef TARGET_SECONDARY_RELOAD
6677 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
6679 #undef TARGET_CLASS_LIKELY_SPILLED_P
6680 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
6682 #undef TARGET_DELEGITIMIZE_ADDRESS
6683 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
6685 #undef TARGET_CANNOT_FORCE_CONST_MEM
6686 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
6688 #undef TARGET_RETURN_IN_MEMORY
6689 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
6691 #undef TARGET_LEGITIMATE_ADDRESS_P
6692 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
6694 #undef TARGET_FRAME_POINTER_REQUIRED
6695 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
6697 #undef TARGET_CAN_ELIMINATE
6698 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
6700 #undef TARGET_CONDITIONAL_REGISTER_USAGE
6701 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
6703 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
6704 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
6705 #undef TARGET_TRAMPOLINE_INIT
6706 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
6708 struct gcc_target targetm = TARGET_INITIALIZER;