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