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