]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/bfin/bfin.c
tree.h: Include real.h and fixed-value.h as basic datatypes.
[thirdparty/gcc.git] / gcc / config / bfin / bfin.c
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Analog Devices.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 3, or (at your
11 option) any later version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "insn-codes.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
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 /* Write a template for a trampoline to F. */
2098
2099 static void
2100 bfin_asm_trampoline_template (FILE *f)
2101 {
2102 if (TARGET_FDPIC)
2103 {
2104 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
2105 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
2106 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
2107 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
2108 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
2109 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
2110 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
2111 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
2112 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
2113 }
2114 else
2115 {
2116 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
2117 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
2118 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
2119 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
2120 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
2121 }
2122 }
2123
2124 /* Emit RTL insns to initialize the variable parts of a trampoline at
2125 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
2126 the static chain value for the function. */
2127
2128 static void
2129 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2130 {
2131 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
2132 rtx t2 = copy_to_reg (chain_value);
2133 rtx mem;
2134 int i = 0;
2135
2136 emit_block_move (m_tramp, assemble_trampoline_template (),
2137 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2138
2139 if (TARGET_FDPIC)
2140 {
2141 rtx a = force_reg (Pmode, plus_constant (XEXP (m_tramp, 0), 8));
2142 mem = adjust_address (m_tramp, Pmode, 0);
2143 emit_move_insn (mem, a);
2144 i = 8;
2145 }
2146
2147 mem = adjust_address (m_tramp, HImode, i + 2);
2148 emit_move_insn (mem, gen_lowpart (HImode, t1));
2149 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
2150 mem = adjust_address (m_tramp, HImode, i + 6);
2151 emit_move_insn (mem, gen_lowpart (HImode, t1));
2152
2153 mem = adjust_address (m_tramp, HImode, i + 10);
2154 emit_move_insn (mem, gen_lowpart (HImode, t2));
2155 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
2156 mem = adjust_address (m_tramp, HImode, i + 14);
2157 emit_move_insn (mem, gen_lowpart (HImode, t2));
2158 }
2159
2160 /* Emit insns to move operands[1] into operands[0]. */
2161
2162 void
2163 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
2164 {
2165 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2166
2167 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
2168 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2169 operands[1] = force_reg (SImode, operands[1]);
2170 else
2171 operands[1] = legitimize_pic_address (operands[1], temp,
2172 TARGET_FDPIC ? OUR_FDPIC_REG
2173 : pic_offset_table_rtx);
2174 }
2175
2176 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
2177 Returns true if no further code must be generated, false if the caller
2178 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
2179
2180 bool
2181 expand_move (rtx *operands, enum machine_mode mode)
2182 {
2183 rtx op = operands[1];
2184 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
2185 && SYMBOLIC_CONST (op))
2186 emit_pic_move (operands, mode);
2187 else if (mode == SImode && GET_CODE (op) == CONST
2188 && GET_CODE (XEXP (op, 0)) == PLUS
2189 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
2190 && !bfin_legitimate_constant_p (op))
2191 {
2192 rtx dest = operands[0];
2193 rtx op0, op1;
2194 gcc_assert (!reload_in_progress && !reload_completed);
2195 op = XEXP (op, 0);
2196 op0 = force_reg (mode, XEXP (op, 0));
2197 op1 = XEXP (op, 1);
2198 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
2199 op1 = force_reg (mode, op1);
2200 if (GET_CODE (dest) == MEM)
2201 dest = gen_reg_rtx (mode);
2202 emit_insn (gen_addsi3 (dest, op0, op1));
2203 if (dest == operands[0])
2204 return true;
2205 operands[1] = dest;
2206 }
2207 /* Don't generate memory->memory or constant->memory moves, go through a
2208 register */
2209 else if ((reload_in_progress | reload_completed) == 0
2210 && GET_CODE (operands[0]) == MEM
2211 && GET_CODE (operands[1]) != REG)
2212 operands[1] = force_reg (mode, operands[1]);
2213 return false;
2214 }
2215 \f
2216 /* Split one or more DImode RTL references into pairs of SImode
2217 references. The RTL can be REG, offsettable MEM, integer constant, or
2218 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2219 split and "num" is its length. lo_half and hi_half are output arrays
2220 that parallel "operands". */
2221
2222 void
2223 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
2224 {
2225 while (num--)
2226 {
2227 rtx op = operands[num];
2228
2229 /* simplify_subreg refuse to split volatile memory addresses,
2230 but we still have to handle it. */
2231 if (GET_CODE (op) == MEM)
2232 {
2233 lo_half[num] = adjust_address (op, SImode, 0);
2234 hi_half[num] = adjust_address (op, SImode, 4);
2235 }
2236 else
2237 {
2238 lo_half[num] = simplify_gen_subreg (SImode, op,
2239 GET_MODE (op) == VOIDmode
2240 ? DImode : GET_MODE (op), 0);
2241 hi_half[num] = simplify_gen_subreg (SImode, op,
2242 GET_MODE (op) == VOIDmode
2243 ? DImode : GET_MODE (op), 4);
2244 }
2245 }
2246 }
2247 \f
2248 bool
2249 bfin_longcall_p (rtx op, int call_cookie)
2250 {
2251 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2252 if (SYMBOL_REF_WEAK (op))
2253 return 1;
2254 if (call_cookie & CALL_SHORT)
2255 return 0;
2256 if (call_cookie & CALL_LONG)
2257 return 1;
2258 if (TARGET_LONG_CALLS)
2259 return 1;
2260 return 0;
2261 }
2262
2263 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2264 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2265 SIBCALL is nonzero if this is a sibling call. */
2266
2267 void
2268 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2269 {
2270 rtx use = NULL, call;
2271 rtx callee = XEXP (fnaddr, 0);
2272 int nelts = 3;
2273 rtx pat;
2274 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2275 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2276 int n;
2277
2278 /* In an untyped call, we can get NULL for operand 2. */
2279 if (cookie == NULL_RTX)
2280 cookie = const0_rtx;
2281
2282 /* Static functions and indirect calls don't need the pic register. */
2283 if (!TARGET_FDPIC && flag_pic
2284 && GET_CODE (callee) == SYMBOL_REF
2285 && !SYMBOL_REF_LOCAL_P (callee))
2286 use_reg (&use, pic_offset_table_rtx);
2287
2288 if (TARGET_FDPIC)
2289 {
2290 int caller_in_sram, callee_in_sram;
2291
2292 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2293 caller_in_sram = callee_in_sram = 0;
2294
2295 if (lookup_attribute ("l1_text",
2296 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2297 caller_in_sram = 1;
2298 else if (lookup_attribute ("l2",
2299 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2300 caller_in_sram = 2;
2301
2302 if (GET_CODE (callee) == SYMBOL_REF
2303 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2304 {
2305 if (lookup_attribute
2306 ("l1_text",
2307 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2308 callee_in_sram = 1;
2309 else if (lookup_attribute
2310 ("l2",
2311 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2312 callee_in_sram = 2;
2313 }
2314
2315 if (GET_CODE (callee) != SYMBOL_REF
2316 || bfin_longcall_p (callee, INTVAL (cookie))
2317 || (GET_CODE (callee) == SYMBOL_REF
2318 && !SYMBOL_REF_LOCAL_P (callee)
2319 && TARGET_INLINE_PLT)
2320 || caller_in_sram != callee_in_sram
2321 || (caller_in_sram && callee_in_sram
2322 && (GET_CODE (callee) != SYMBOL_REF
2323 || !SYMBOL_REF_LOCAL_P (callee))))
2324 {
2325 rtx addr = callee;
2326 if (! address_operand (addr, Pmode))
2327 addr = force_reg (Pmode, addr);
2328
2329 fnaddr = gen_reg_rtx (SImode);
2330 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2331 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2332
2333 picreg = gen_reg_rtx (SImode);
2334 emit_insn (gen_load_funcdescsi (picreg,
2335 plus_constant (addr, 4)));
2336 }
2337
2338 nelts++;
2339 }
2340 else if ((!register_no_elim_operand (callee, Pmode)
2341 && GET_CODE (callee) != SYMBOL_REF)
2342 || (GET_CODE (callee) == SYMBOL_REF
2343 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2344 || bfin_longcall_p (callee, INTVAL (cookie)))))
2345 {
2346 callee = copy_to_mode_reg (Pmode, callee);
2347 fnaddr = gen_rtx_MEM (Pmode, callee);
2348 }
2349 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2350
2351 if (retval)
2352 call = gen_rtx_SET (VOIDmode, retval, call);
2353
2354 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2355 n = 0;
2356 XVECEXP (pat, 0, n++) = call;
2357 if (TARGET_FDPIC)
2358 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2359 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2360 if (sibcall)
2361 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
2362 else
2363 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2364 call = emit_call_insn (pat);
2365 if (use)
2366 CALL_INSN_FUNCTION_USAGE (call) = use;
2367 }
2368 \f
2369 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2370
2371 int
2372 hard_regno_mode_ok (int regno, enum machine_mode mode)
2373 {
2374 /* Allow only dregs to store value of mode HI or QI */
2375 enum reg_class rclass = REGNO_REG_CLASS (regno);
2376
2377 if (mode == CCmode)
2378 return 0;
2379
2380 if (mode == V2HImode)
2381 return D_REGNO_P (regno);
2382 if (rclass == CCREGS)
2383 return mode == BImode;
2384 if (mode == PDImode || mode == V2PDImode)
2385 return regno == REG_A0 || regno == REG_A1;
2386
2387 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2388 up with a bad register class (such as ALL_REGS) for DImode. */
2389 if (mode == DImode)
2390 return regno < REG_M3;
2391
2392 if (mode == SImode
2393 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2394 return 1;
2395
2396 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2397 }
2398
2399 /* Implements target hook vector_mode_supported_p. */
2400
2401 static bool
2402 bfin_vector_mode_supported_p (enum machine_mode mode)
2403 {
2404 return mode == V2HImode;
2405 }
2406
2407 /* Return the cost of moving data from a register in class CLASS1 to
2408 one in class CLASS2. A cost of 2 is the default. */
2409
2410 int
2411 bfin_register_move_cost (enum machine_mode mode,
2412 enum reg_class class1, enum reg_class class2)
2413 {
2414 /* These need secondary reloads, so they're more expensive. */
2415 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2416 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2417 return 4;
2418
2419 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2420 if (optimize_size)
2421 return 2;
2422
2423 if (GET_MODE_CLASS (mode) == MODE_INT)
2424 {
2425 /* Discourage trying to use the accumulators. */
2426 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2427 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2428 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2429 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2430 return 20;
2431 }
2432 return 2;
2433 }
2434
2435 /* Return the cost of moving data of mode M between a
2436 register and memory. A value of 2 is the default; this cost is
2437 relative to those in `REGISTER_MOVE_COST'.
2438
2439 ??? In theory L1 memory has single-cycle latency. We should add a switch
2440 that tells the compiler whether we expect to use only L1 memory for the
2441 program; it'll make the costs more accurate. */
2442
2443 int
2444 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2445 enum reg_class rclass,
2446 int in ATTRIBUTE_UNUSED)
2447 {
2448 /* Make memory accesses slightly more expensive than any register-register
2449 move. Also, penalize non-DP registers, since they need secondary
2450 reloads to load and store. */
2451 if (! reg_class_subset_p (rclass, DPREGS))
2452 return 10;
2453
2454 return 8;
2455 }
2456
2457 /* Inform reload about cases where moving X with a mode MODE to a register in
2458 RCLASS requires an extra scratch register. Return the class needed for the
2459 scratch register. */
2460
2461 static enum reg_class
2462 bfin_secondary_reload (bool in_p, rtx x, enum reg_class rclass,
2463 enum machine_mode mode, secondary_reload_info *sri)
2464 {
2465 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2466 in most other cases we can also use PREGS. */
2467 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2468 enum reg_class x_class = NO_REGS;
2469 enum rtx_code code = GET_CODE (x);
2470
2471 if (code == SUBREG)
2472 x = SUBREG_REG (x), code = GET_CODE (x);
2473 if (REG_P (x))
2474 {
2475 int regno = REGNO (x);
2476 if (regno >= FIRST_PSEUDO_REGISTER)
2477 regno = reg_renumber[regno];
2478
2479 if (regno == -1)
2480 code = MEM;
2481 else
2482 x_class = REGNO_REG_CLASS (regno);
2483 }
2484
2485 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2486 This happens as a side effect of register elimination, and we need
2487 a scratch register to do it. */
2488 if (fp_plus_const_operand (x, mode))
2489 {
2490 rtx op2 = XEXP (x, 1);
2491 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2492
2493 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2494 return NO_REGS;
2495 /* If destination is a DREG, we can do this without a scratch register
2496 if the constant is valid for an add instruction. */
2497 if ((rclass == DREGS || rclass == DPREGS)
2498 && ! large_constant_p)
2499 return NO_REGS;
2500 /* Reloading to anything other than a DREG? Use a PREG scratch
2501 register. */
2502 sri->icode = CODE_FOR_reload_insi;
2503 return NO_REGS;
2504 }
2505
2506 /* Data can usually be moved freely between registers of most classes.
2507 AREGS are an exception; they can only move to or from another register
2508 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2509 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2510 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2511 || rclass == ODD_AREGS
2512 ? NO_REGS : DREGS);
2513
2514 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2515 {
2516 if (code == MEM)
2517 {
2518 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2519 return NO_REGS;
2520 }
2521
2522 if (x != const0_rtx && x_class != DREGS)
2523 {
2524 return DREGS;
2525 }
2526 else
2527 return NO_REGS;
2528 }
2529
2530 /* CCREGS can only be moved from/to DREGS. */
2531 if (rclass == CCREGS && x_class != DREGS)
2532 return DREGS;
2533 if (x_class == CCREGS && rclass != DREGS)
2534 return DREGS;
2535
2536 /* All registers other than AREGS can load arbitrary constants. The only
2537 case that remains is MEM. */
2538 if (code == MEM)
2539 if (! reg_class_subset_p (rclass, default_class))
2540 return default_class;
2541
2542 return NO_REGS;
2543 }
2544 \f
2545 /* Implement TARGET_HANDLE_OPTION. */
2546
2547 static bool
2548 bfin_handle_option (size_t code, const char *arg, int value)
2549 {
2550 switch (code)
2551 {
2552 case OPT_mshared_library_id_:
2553 if (value > MAX_LIBRARY_ID)
2554 error ("-mshared-library-id=%s is not between 0 and %d",
2555 arg, MAX_LIBRARY_ID);
2556 bfin_lib_id_given = 1;
2557 return true;
2558
2559 case OPT_mcpu_:
2560 {
2561 const char *p, *q;
2562 int i;
2563
2564 i = 0;
2565 while ((p = bfin_cpus[i].name) != NULL)
2566 {
2567 if (strncmp (arg, p, strlen (p)) == 0)
2568 break;
2569 i++;
2570 }
2571
2572 if (p == NULL)
2573 {
2574 error ("-mcpu=%s is not valid", arg);
2575 return false;
2576 }
2577
2578 bfin_cpu_type = bfin_cpus[i].type;
2579
2580 q = arg + strlen (p);
2581
2582 if (*q == '\0')
2583 {
2584 bfin_si_revision = bfin_cpus[i].si_revision;
2585 bfin_workarounds |= bfin_cpus[i].workarounds;
2586 }
2587 else if (strcmp (q, "-none") == 0)
2588 bfin_si_revision = -1;
2589 else if (strcmp (q, "-any") == 0)
2590 {
2591 bfin_si_revision = 0xffff;
2592 while (bfin_cpus[i].type == bfin_cpu_type)
2593 {
2594 bfin_workarounds |= bfin_cpus[i].workarounds;
2595 i++;
2596 }
2597 }
2598 else
2599 {
2600 unsigned int si_major, si_minor;
2601 int rev_len, n;
2602
2603 rev_len = strlen (q);
2604
2605 if (sscanf (q, "-%u.%u%n", &si_major, &si_minor, &n) != 2
2606 || n != rev_len
2607 || si_major > 0xff || si_minor > 0xff)
2608 {
2609 invalid_silicon_revision:
2610 error ("-mcpu=%s has invalid silicon revision", arg);
2611 return false;
2612 }
2613
2614 bfin_si_revision = (si_major << 8) | si_minor;
2615
2616 while (bfin_cpus[i].type == bfin_cpu_type
2617 && bfin_cpus[i].si_revision != bfin_si_revision)
2618 i++;
2619
2620 if (bfin_cpus[i].type != bfin_cpu_type)
2621 goto invalid_silicon_revision;
2622
2623 bfin_workarounds |= bfin_cpus[i].workarounds;
2624 }
2625
2626 return true;
2627 }
2628
2629 default:
2630 return true;
2631 }
2632 }
2633
2634 static struct machine_function *
2635 bfin_init_machine_status (void)
2636 {
2637 struct machine_function *f;
2638
2639 f = GGC_CNEW (struct machine_function);
2640
2641 return f;
2642 }
2643
2644 /* Implement the macro OVERRIDE_OPTIONS. */
2645
2646 void
2647 override_options (void)
2648 {
2649 /* If processor type is not specified, enable all workarounds. */
2650 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2651 {
2652 int i;
2653
2654 for (i = 0; bfin_cpus[i].name != NULL; i++)
2655 bfin_workarounds |= bfin_cpus[i].workarounds;
2656
2657 bfin_si_revision = 0xffff;
2658 }
2659
2660 if (bfin_csync_anomaly == 1)
2661 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2662 else if (bfin_csync_anomaly == 0)
2663 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2664
2665 if (bfin_specld_anomaly == 1)
2666 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2667 else if (bfin_specld_anomaly == 0)
2668 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2669
2670 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2671 flag_omit_frame_pointer = 1;
2672
2673 /* Library identification */
2674 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2675 error ("-mshared-library-id= specified without -mid-shared-library");
2676
2677 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2678 error ("Can't use multiple stack checking methods together.");
2679
2680 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2681 error ("ID shared libraries and FD-PIC mode can't be used together.");
2682
2683 /* Don't allow the user to specify -mid-shared-library and -msep-data
2684 together, as it makes little sense from a user's point of view... */
2685 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2686 error ("cannot specify both -msep-data and -mid-shared-library");
2687 /* ... internally, however, it's nearly the same. */
2688 if (TARGET_SEP_DATA)
2689 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2690
2691 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2692 flag_pic = 1;
2693
2694 /* There is no single unaligned SI op for PIC code. Sometimes we
2695 need to use ".4byte" and sometimes we need to use ".picptr".
2696 See bfin_assemble_integer for details. */
2697 if (TARGET_FDPIC)
2698 targetm.asm_out.unaligned_op.si = 0;
2699
2700 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2701 since we don't support it and it'll just break. */
2702 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2703 flag_pic = 0;
2704
2705 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2706 error ("-mmulticore can only be used with BF561");
2707
2708 if (TARGET_COREA && !TARGET_MULTICORE)
2709 error ("-mcorea should be used with -mmulticore");
2710
2711 if (TARGET_COREB && !TARGET_MULTICORE)
2712 error ("-mcoreb should be used with -mmulticore");
2713
2714 if (TARGET_COREA && TARGET_COREB)
2715 error ("-mcorea and -mcoreb can't be used together");
2716
2717 flag_schedule_insns = 0;
2718
2719 /* Passes after sched2 can break the helpful TImode annotations that
2720 haifa-sched puts on every insn. Just do scheduling in reorg. */
2721 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2722 flag_schedule_insns_after_reload = 0;
2723
2724 init_machine_status = bfin_init_machine_status;
2725 }
2726
2727 /* Return the destination address of BRANCH.
2728 We need to use this instead of get_attr_length, because the
2729 cbranch_with_nops pattern conservatively sets its length to 6, and
2730 we still prefer to use shorter sequences. */
2731
2732 static int
2733 branch_dest (rtx branch)
2734 {
2735 rtx dest;
2736 int dest_uid;
2737 rtx pat = PATTERN (branch);
2738 if (GET_CODE (pat) == PARALLEL)
2739 pat = XVECEXP (pat, 0, 0);
2740 dest = SET_SRC (pat);
2741 if (GET_CODE (dest) == IF_THEN_ELSE)
2742 dest = XEXP (dest, 1);
2743 dest = XEXP (dest, 0);
2744 dest_uid = INSN_UID (dest);
2745 return INSN_ADDRESSES (dest_uid);
2746 }
2747
2748 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2749 it's a branch that's predicted taken. */
2750
2751 static int
2752 cbranch_predicted_taken_p (rtx insn)
2753 {
2754 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2755
2756 if (x)
2757 {
2758 int pred_val = INTVAL (XEXP (x, 0));
2759
2760 return pred_val >= REG_BR_PROB_BASE / 2;
2761 }
2762
2763 return 0;
2764 }
2765
2766 /* Templates for use by asm_conditional_branch. */
2767
2768 static const char *ccbranch_templates[][3] = {
2769 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2770 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2771 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2772 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2773 };
2774
2775 /* Output INSN, which is a conditional branch instruction with operands
2776 OPERANDS.
2777
2778 We deal with the various forms of conditional branches that can be generated
2779 by bfin_reorg to prevent the hardware from doing speculative loads, by
2780 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2781 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2782 Either of these is only necessary if the branch is short, otherwise the
2783 template we use ends in an unconditional jump which flushes the pipeline
2784 anyway. */
2785
2786 void
2787 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2788 {
2789 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2790 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2791 is to be taken from start of if cc rather than jump.
2792 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2793 */
2794 int len = (offset >= -1024 && offset <= 1022 ? 0
2795 : offset >= -4094 && offset <= 4096 ? 1
2796 : 2);
2797 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2798 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2799 output_asm_insn (ccbranch_templates[idx][len], operands);
2800 gcc_assert (n_nops == 0 || !bp);
2801 if (len == 0)
2802 while (n_nops-- > 0)
2803 output_asm_insn ("nop;", NULL);
2804 }
2805
2806 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2807 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2808
2809 rtx
2810 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2811 {
2812 enum rtx_code code1, code2;
2813 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2814 rtx tem = bfin_cc_rtx;
2815 enum rtx_code code = GET_CODE (cmp);
2816
2817 /* If we have a BImode input, then we already have a compare result, and
2818 do not need to emit another comparison. */
2819 if (GET_MODE (op0) == BImode)
2820 {
2821 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2822 tem = op0, code2 = code;
2823 }
2824 else
2825 {
2826 switch (code) {
2827 /* bfin has these conditions */
2828 case EQ:
2829 case LT:
2830 case LE:
2831 case LEU:
2832 case LTU:
2833 code1 = code;
2834 code2 = NE;
2835 break;
2836 default:
2837 code1 = reverse_condition (code);
2838 code2 = EQ;
2839 break;
2840 }
2841 emit_insn (gen_rtx_SET (VOIDmode, tem,
2842 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2843 }
2844
2845 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2846 }
2847 \f
2848 /* Return nonzero iff C has exactly one bit set if it is interpreted
2849 as a 32-bit constant. */
2850
2851 int
2852 log2constp (unsigned HOST_WIDE_INT c)
2853 {
2854 c &= 0xFFFFFFFF;
2855 return c != 0 && (c & (c-1)) == 0;
2856 }
2857
2858 /* Returns the number of consecutive least significant zeros in the binary
2859 representation of *V.
2860 We modify *V to contain the original value arithmetically shifted right by
2861 the number of zeroes. */
2862
2863 static int
2864 shiftr_zero (HOST_WIDE_INT *v)
2865 {
2866 unsigned HOST_WIDE_INT tmp = *v;
2867 unsigned HOST_WIDE_INT sgn;
2868 int n = 0;
2869
2870 if (tmp == 0)
2871 return 0;
2872
2873 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2874 while ((tmp & 0x1) == 0 && n <= 32)
2875 {
2876 tmp = (tmp >> 1) | sgn;
2877 n++;
2878 }
2879 *v = tmp;
2880 return n;
2881 }
2882
2883 /* After reload, split the load of an immediate constant. OPERANDS are the
2884 operands of the movsi_insn pattern which we are splitting. We return
2885 nonzero if we emitted a sequence to load the constant, zero if we emitted
2886 nothing because we want to use the splitter's default sequence. */
2887
2888 int
2889 split_load_immediate (rtx operands[])
2890 {
2891 HOST_WIDE_INT val = INTVAL (operands[1]);
2892 HOST_WIDE_INT tmp;
2893 HOST_WIDE_INT shifted = val;
2894 HOST_WIDE_INT shifted_compl = ~val;
2895 int num_zero = shiftr_zero (&shifted);
2896 int num_compl_zero = shiftr_zero (&shifted_compl);
2897 unsigned int regno = REGNO (operands[0]);
2898
2899 /* This case takes care of single-bit set/clear constants, which we could
2900 also implement with BITSET/BITCLR. */
2901 if (num_zero
2902 && shifted >= -32768 && shifted < 65536
2903 && (D_REGNO_P (regno)
2904 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2905 {
2906 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2907 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2908 return 1;
2909 }
2910
2911 tmp = val & 0xFFFF;
2912 tmp |= -(tmp & 0x8000);
2913
2914 /* If high word has one bit set or clear, try to use a bit operation. */
2915 if (D_REGNO_P (regno))
2916 {
2917 if (log2constp (val & 0xFFFF0000))
2918 {
2919 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2920 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2921 return 1;
2922 }
2923 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2924 {
2925 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2926 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2927 }
2928 }
2929
2930 if (D_REGNO_P (regno))
2931 {
2932 if (tmp >= -64 && tmp <= 63)
2933 {
2934 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2935 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2936 return 1;
2937 }
2938
2939 if ((val & 0xFFFF0000) == 0)
2940 {
2941 emit_insn (gen_movsi (operands[0], const0_rtx));
2942 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2943 return 1;
2944 }
2945
2946 if ((val & 0xFFFF0000) == 0xFFFF0000)
2947 {
2948 emit_insn (gen_movsi (operands[0], constm1_rtx));
2949 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2950 return 1;
2951 }
2952 }
2953
2954 /* Need DREGs for the remaining case. */
2955 if (regno > REG_R7)
2956 return 0;
2957
2958 if (optimize_size
2959 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2960 {
2961 /* If optimizing for size, generate a sequence that has more instructions
2962 but is shorter. */
2963 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2964 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2965 GEN_INT (num_compl_zero)));
2966 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2967 return 1;
2968 }
2969 return 0;
2970 }
2971 \f
2972 /* Return true if the legitimate memory address for a memory operand of mode
2973 MODE. Return false if not. */
2974
2975 static bool
2976 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2977 {
2978 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2979 int sz = GET_MODE_SIZE (mode);
2980 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2981 /* The usual offsettable_memref machinery doesn't work so well for this
2982 port, so we deal with the problem here. */
2983 if (value > 0 && sz == 8)
2984 v += 4;
2985 return (v & ~(0x7fff << shift)) == 0;
2986 }
2987
2988 static bool
2989 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2990 enum rtx_code outer_code)
2991 {
2992 if (strict)
2993 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2994 else
2995 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2996 }
2997
2998 /* Recognize an RTL expression that is a valid memory address for an
2999 instruction. The MODE argument is the machine mode for the MEM expression
3000 that wants to use this address.
3001
3002 Blackfin addressing modes are as follows:
3003
3004 [preg]
3005 [preg + imm16]
3006
3007 B [ Preg + uimm15 ]
3008 W [ Preg + uimm16m2 ]
3009 [ Preg + uimm17m4 ]
3010
3011 [preg++]
3012 [preg--]
3013 [--sp]
3014 */
3015
3016 static bool
3017 bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
3018 {
3019 switch (GET_CODE (x)) {
3020 case REG:
3021 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
3022 return true;
3023 break;
3024 case PLUS:
3025 if (REG_P (XEXP (x, 0))
3026 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
3027 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
3028 || (GET_CODE (XEXP (x, 1)) == CONST_INT
3029 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
3030 return true;
3031 break;
3032 case POST_INC:
3033 case POST_DEC:
3034 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
3035 && REG_P (XEXP (x, 0))
3036 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
3037 return true;
3038 case PRE_DEC:
3039 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
3040 && XEXP (x, 0) == stack_pointer_rtx
3041 && REG_P (XEXP (x, 0))
3042 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
3043 return true;
3044 break;
3045 default:
3046 break;
3047 }
3048 return false;
3049 }
3050
3051 /* Decide whether we can force certain constants to memory. If we
3052 decide we can't, the caller should be able to cope with it in
3053 another way. */
3054
3055 static bool
3056 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
3057 {
3058 /* We have only one class of non-legitimate constants, and our movsi
3059 expander knows how to handle them. Dropping these constants into the
3060 data section would only shift the problem - we'd still get relocs
3061 outside the object, in the data section rather than the text section. */
3062 return true;
3063 }
3064
3065 /* Ensure that for any constant of the form symbol + offset, the offset
3066 remains within the object. Any other constants are ok.
3067 This ensures that flat binaries never have to deal with relocations
3068 crossing section boundaries. */
3069
3070 bool
3071 bfin_legitimate_constant_p (rtx x)
3072 {
3073 rtx sym;
3074 HOST_WIDE_INT offset;
3075
3076 if (GET_CODE (x) != CONST)
3077 return true;
3078
3079 x = XEXP (x, 0);
3080 gcc_assert (GET_CODE (x) == PLUS);
3081
3082 sym = XEXP (x, 0);
3083 x = XEXP (x, 1);
3084 if (GET_CODE (sym) != SYMBOL_REF
3085 || GET_CODE (x) != CONST_INT)
3086 return true;
3087 offset = INTVAL (x);
3088
3089 if (SYMBOL_REF_DECL (sym) == 0)
3090 return true;
3091 if (offset < 0
3092 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
3093 return false;
3094
3095 return true;
3096 }
3097
3098 static bool
3099 bfin_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
3100 {
3101 int cost2 = COSTS_N_INSNS (1);
3102 rtx op0, op1;
3103
3104 switch (code)
3105 {
3106 case CONST_INT:
3107 if (outer_code == SET || outer_code == PLUS)
3108 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
3109 else if (outer_code == AND)
3110 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
3111 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
3112 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
3113 else if (outer_code == LEU || outer_code == LTU)
3114 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
3115 else if (outer_code == MULT)
3116 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
3117 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
3118 *total = 0;
3119 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
3120 || outer_code == LSHIFTRT)
3121 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
3122 else if (outer_code == IOR || outer_code == XOR)
3123 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
3124 else
3125 *total = cost2;
3126 return true;
3127
3128 case CONST:
3129 case LABEL_REF:
3130 case SYMBOL_REF:
3131 case CONST_DOUBLE:
3132 *total = COSTS_N_INSNS (2);
3133 return true;
3134
3135 case PLUS:
3136 op0 = XEXP (x, 0);
3137 op1 = XEXP (x, 1);
3138 if (GET_MODE (x) == SImode)
3139 {
3140 if (GET_CODE (op0) == MULT
3141 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
3142 {
3143 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
3144 if (val == 2 || val == 4)
3145 {
3146 *total = cost2;
3147 *total += rtx_cost (XEXP (op0, 0), outer_code, speed);
3148 *total += rtx_cost (op1, outer_code, speed);
3149 return true;
3150 }
3151 }
3152 *total = cost2;
3153 if (GET_CODE (op0) != REG
3154 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3155 *total += rtx_cost (op0, SET, speed);
3156 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
3157 towards creating too many induction variables. */
3158 if (!reg_or_7bit_operand (op1, SImode))
3159 *total += rtx_cost (op1, SET, speed);
3160 #endif
3161 }
3162 else if (GET_MODE (x) == DImode)
3163 {
3164 *total = 6 * cost2;
3165 if (GET_CODE (op1) != CONST_INT
3166 || !satisfies_constraint_Ks7 (op1))
3167 *total += rtx_cost (op1, PLUS, speed);
3168 if (GET_CODE (op0) != REG
3169 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3170 *total += rtx_cost (op0, PLUS, speed);
3171 }
3172 return true;
3173
3174 case MINUS:
3175 if (GET_MODE (x) == DImode)
3176 *total = 6 * cost2;
3177 else
3178 *total = cost2;
3179 return true;
3180
3181 case ASHIFT:
3182 case ASHIFTRT:
3183 case LSHIFTRT:
3184 if (GET_MODE (x) == DImode)
3185 *total = 6 * cost2;
3186 else
3187 *total = cost2;
3188
3189 op0 = XEXP (x, 0);
3190 op1 = XEXP (x, 1);
3191 if (GET_CODE (op0) != REG
3192 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3193 *total += rtx_cost (op0, code, speed);
3194
3195 return true;
3196
3197 case IOR:
3198 case AND:
3199 case XOR:
3200 op0 = XEXP (x, 0);
3201 op1 = XEXP (x, 1);
3202
3203 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
3204 if (code == IOR)
3205 {
3206 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
3207 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
3208 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
3209 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
3210 {
3211 *total = cost2;
3212 return true;
3213 }
3214 }
3215
3216 if (GET_CODE (op0) != REG
3217 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3218 *total += rtx_cost (op0, code, speed);
3219
3220 if (GET_MODE (x) == DImode)
3221 {
3222 *total = 2 * cost2;
3223 return true;
3224 }
3225 *total = cost2;
3226 if (GET_MODE (x) != SImode)
3227 return true;
3228
3229 if (code == AND)
3230 {
3231 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
3232 *total += rtx_cost (XEXP (x, 1), code, speed);
3233 }
3234 else
3235 {
3236 if (! regorlog2_operand (XEXP (x, 1), SImode))
3237 *total += rtx_cost (XEXP (x, 1), code, speed);
3238 }
3239
3240 return true;
3241
3242 case ZERO_EXTRACT:
3243 case SIGN_EXTRACT:
3244 if (outer_code == SET
3245 && XEXP (x, 1) == const1_rtx
3246 && GET_CODE (XEXP (x, 2)) == CONST_INT)
3247 {
3248 *total = 2 * cost2;
3249 return true;
3250 }
3251 /* fall through */
3252
3253 case SIGN_EXTEND:
3254 case ZERO_EXTEND:
3255 *total = cost2;
3256 return true;
3257
3258 case MULT:
3259 {
3260 op0 = XEXP (x, 0);
3261 op1 = XEXP (x, 1);
3262 if (GET_CODE (op0) == GET_CODE (op1)
3263 && (GET_CODE (op0) == ZERO_EXTEND
3264 || GET_CODE (op0) == SIGN_EXTEND))
3265 {
3266 *total = COSTS_N_INSNS (1);
3267 op0 = XEXP (op0, 0);
3268 op1 = XEXP (op1, 0);
3269 }
3270 else if (!speed)
3271 *total = COSTS_N_INSNS (1);
3272 else
3273 *total = COSTS_N_INSNS (3);
3274
3275 if (GET_CODE (op0) != REG
3276 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3277 *total += rtx_cost (op0, MULT, speed);
3278 if (GET_CODE (op1) != REG
3279 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3280 *total += rtx_cost (op1, MULT, speed);
3281 }
3282 return true;
3283
3284 case UDIV:
3285 case UMOD:
3286 *total = COSTS_N_INSNS (32);
3287 return true;
3288
3289 case VEC_CONCAT:
3290 case VEC_SELECT:
3291 if (outer_code == SET)
3292 *total = cost2;
3293 return true;
3294
3295 default:
3296 return false;
3297 }
3298 }
3299 \f
3300 /* Used for communication between {push,pop}_multiple_operation (which
3301 we use not only as a predicate) and the corresponding output functions. */
3302 static int first_preg_to_save, first_dreg_to_save;
3303 static int n_regs_to_save;
3304
3305 int
3306 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3307 {
3308 int lastdreg = 8, lastpreg = 6;
3309 int i, group;
3310
3311 first_preg_to_save = lastpreg;
3312 first_dreg_to_save = lastdreg;
3313 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3314 {
3315 rtx t = XVECEXP (op, 0, i);
3316 rtx src, dest;
3317 int regno;
3318
3319 if (GET_CODE (t) != SET)
3320 return 0;
3321
3322 src = SET_SRC (t);
3323 dest = SET_DEST (t);
3324 if (GET_CODE (dest) != MEM || ! REG_P (src))
3325 return 0;
3326 dest = XEXP (dest, 0);
3327 if (GET_CODE (dest) != PLUS
3328 || ! REG_P (XEXP (dest, 0))
3329 || REGNO (XEXP (dest, 0)) != REG_SP
3330 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3331 || INTVAL (XEXP (dest, 1)) != -i * 4)
3332 return 0;
3333
3334 regno = REGNO (src);
3335 if (group == 0)
3336 {
3337 if (D_REGNO_P (regno))
3338 {
3339 group = 1;
3340 first_dreg_to_save = lastdreg = regno - REG_R0;
3341 }
3342 else if (regno >= REG_P0 && regno <= REG_P7)
3343 {
3344 group = 2;
3345 first_preg_to_save = lastpreg = regno - REG_P0;
3346 }
3347 else
3348 return 0;
3349
3350 continue;
3351 }
3352
3353 if (group == 1)
3354 {
3355 if (regno >= REG_P0 && regno <= REG_P7)
3356 {
3357 group = 2;
3358 first_preg_to_save = lastpreg = regno - REG_P0;
3359 }
3360 else if (regno != REG_R0 + lastdreg + 1)
3361 return 0;
3362 else
3363 lastdreg++;
3364 }
3365 else if (group == 2)
3366 {
3367 if (regno != REG_P0 + lastpreg + 1)
3368 return 0;
3369 lastpreg++;
3370 }
3371 }
3372 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3373 return 1;
3374 }
3375
3376 int
3377 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3378 {
3379 int lastdreg = 8, lastpreg = 6;
3380 int i, group;
3381
3382 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3383 {
3384 rtx t = XVECEXP (op, 0, i);
3385 rtx src, dest;
3386 int regno;
3387
3388 if (GET_CODE (t) != SET)
3389 return 0;
3390
3391 src = SET_SRC (t);
3392 dest = SET_DEST (t);
3393 if (GET_CODE (src) != MEM || ! REG_P (dest))
3394 return 0;
3395 src = XEXP (src, 0);
3396
3397 if (i == 1)
3398 {
3399 if (! REG_P (src) || REGNO (src) != REG_SP)
3400 return 0;
3401 }
3402 else if (GET_CODE (src) != PLUS
3403 || ! REG_P (XEXP (src, 0))
3404 || REGNO (XEXP (src, 0)) != REG_SP
3405 || GET_CODE (XEXP (src, 1)) != CONST_INT
3406 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3407 return 0;
3408
3409 regno = REGNO (dest);
3410 if (group == 0)
3411 {
3412 if (regno == REG_R7)
3413 {
3414 group = 1;
3415 lastdreg = 7;
3416 }
3417 else if (regno != REG_P0 + lastpreg - 1)
3418 return 0;
3419 else
3420 lastpreg--;
3421 }
3422 else if (group == 1)
3423 {
3424 if (regno != REG_R0 + lastdreg - 1)
3425 return 0;
3426 else
3427 lastdreg--;
3428 }
3429 }
3430 first_dreg_to_save = lastdreg;
3431 first_preg_to_save = lastpreg;
3432 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3433 return 1;
3434 }
3435
3436 /* Emit assembly code for one multi-register push described by INSN, with
3437 operands in OPERANDS. */
3438
3439 void
3440 output_push_multiple (rtx insn, rtx *operands)
3441 {
3442 char buf[80];
3443 int ok;
3444
3445 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3446 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3447 gcc_assert (ok);
3448
3449 if (first_dreg_to_save == 8)
3450 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3451 else if (first_preg_to_save == 6)
3452 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3453 else
3454 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3455 first_dreg_to_save, first_preg_to_save);
3456
3457 output_asm_insn (buf, operands);
3458 }
3459
3460 /* Emit assembly code for one multi-register pop described by INSN, with
3461 operands in OPERANDS. */
3462
3463 void
3464 output_pop_multiple (rtx insn, rtx *operands)
3465 {
3466 char buf[80];
3467 int ok;
3468
3469 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3470 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3471 gcc_assert (ok);
3472
3473 if (first_dreg_to_save == 8)
3474 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3475 else if (first_preg_to_save == 6)
3476 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3477 else
3478 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3479 first_dreg_to_save, first_preg_to_save);
3480
3481 output_asm_insn (buf, operands);
3482 }
3483
3484 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3485
3486 static void
3487 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3488 {
3489 rtx scratch = gen_reg_rtx (mode);
3490 rtx srcmem, dstmem;
3491
3492 srcmem = adjust_address_nv (src, mode, offset);
3493 dstmem = adjust_address_nv (dst, mode, offset);
3494 emit_move_insn (scratch, srcmem);
3495 emit_move_insn (dstmem, scratch);
3496 }
3497
3498 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3499 alignment ALIGN_EXP. Return true if successful, false if we should fall
3500 back on a different method. */
3501
3502 bool
3503 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3504 {
3505 rtx srcreg, destreg, countreg;
3506 HOST_WIDE_INT align = 0;
3507 unsigned HOST_WIDE_INT count = 0;
3508
3509 if (GET_CODE (align_exp) == CONST_INT)
3510 align = INTVAL (align_exp);
3511 if (GET_CODE (count_exp) == CONST_INT)
3512 {
3513 count = INTVAL (count_exp);
3514 #if 0
3515 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3516 return false;
3517 #endif
3518 }
3519
3520 /* If optimizing for size, only do single copies inline. */
3521 if (optimize_size)
3522 {
3523 if (count == 2 && align < 2)
3524 return false;
3525 if (count == 4 && align < 4)
3526 return false;
3527 if (count != 1 && count != 2 && count != 4)
3528 return false;
3529 }
3530 if (align < 2 && count != 1)
3531 return false;
3532
3533 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3534 if (destreg != XEXP (dst, 0))
3535 dst = replace_equiv_address_nv (dst, destreg);
3536 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3537 if (srcreg != XEXP (src, 0))
3538 src = replace_equiv_address_nv (src, srcreg);
3539
3540 if (count != 0 && align >= 2)
3541 {
3542 unsigned HOST_WIDE_INT offset = 0;
3543
3544 if (align >= 4)
3545 {
3546 if ((count & ~3) == 4)
3547 {
3548 single_move_for_movmem (dst, src, SImode, offset);
3549 offset = 4;
3550 }
3551 else if (count & ~3)
3552 {
3553 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3554 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3555
3556 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3557 cfun->machine->has_loopreg_clobber = true;
3558 }
3559 if (count & 2)
3560 {
3561 single_move_for_movmem (dst, src, HImode, offset);
3562 offset += 2;
3563 }
3564 }
3565 else
3566 {
3567 if ((count & ~1) == 2)
3568 {
3569 single_move_for_movmem (dst, src, HImode, offset);
3570 offset = 2;
3571 }
3572 else if (count & ~1)
3573 {
3574 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3575 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3576
3577 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3578 cfun->machine->has_loopreg_clobber = true;
3579 }
3580 }
3581 if (count & 1)
3582 {
3583 single_move_for_movmem (dst, src, QImode, offset);
3584 }
3585 return true;
3586 }
3587 return false;
3588 }
3589 \f
3590 /* Compute the alignment for a local variable.
3591 TYPE is the data type, and ALIGN is the alignment that
3592 the object would ordinarily have. The value of this macro is used
3593 instead of that alignment to align the object. */
3594
3595 int
3596 bfin_local_alignment (tree type, int align)
3597 {
3598 /* Increasing alignment for (relatively) big types allows the builtin
3599 memcpy can use 32 bit loads/stores. */
3600 if (TYPE_SIZE (type)
3601 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3602 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3603 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3604 return 32;
3605 return align;
3606 }
3607 \f
3608 /* Implement TARGET_SCHED_ISSUE_RATE. */
3609
3610 static int
3611 bfin_issue_rate (void)
3612 {
3613 return 3;
3614 }
3615
3616 static int
3617 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3618 {
3619 enum attr_type insn_type, dep_insn_type;
3620 int dep_insn_code_number;
3621
3622 /* Anti and output dependencies have zero cost. */
3623 if (REG_NOTE_KIND (link) != 0)
3624 return 0;
3625
3626 dep_insn_code_number = recog_memoized (dep_insn);
3627
3628 /* If we can't recognize the insns, we can't really do anything. */
3629 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3630 return cost;
3631
3632 insn_type = get_attr_type (insn);
3633 dep_insn_type = get_attr_type (dep_insn);
3634
3635 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3636 {
3637 rtx pat = PATTERN (dep_insn);
3638 if (GET_CODE (pat) == PARALLEL)
3639 pat = XVECEXP (pat, 0, 0);
3640 rtx dest = SET_DEST (pat);
3641 rtx src = SET_SRC (pat);
3642 if (! ADDRESS_REGNO_P (REGNO (dest))
3643 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3644 return cost;
3645 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3646 }
3647
3648 return cost;
3649 }
3650 \f
3651 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3652 skips all subsequent parallel instructions if INSN is the start of such
3653 a group. */
3654 static rtx
3655 find_next_insn_start (rtx insn)
3656 {
3657 if (GET_MODE (insn) == SImode)
3658 {
3659 while (GET_MODE (insn) != QImode)
3660 insn = NEXT_INSN (insn);
3661 }
3662 return NEXT_INSN (insn);
3663 }
3664
3665 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3666 skips all subsequent parallel instructions if INSN is the start of such
3667 a group. */
3668 static rtx
3669 find_prev_insn_start (rtx insn)
3670 {
3671 insn = PREV_INSN (insn);
3672 gcc_assert (GET_MODE (insn) != SImode);
3673 if (GET_MODE (insn) == QImode)
3674 {
3675 while (GET_MODE (PREV_INSN (insn)) == SImode)
3676 insn = PREV_INSN (insn);
3677 }
3678 return insn;
3679 }
3680 \f
3681 /* Increment the counter for the number of loop instructions in the
3682 current function. */
3683
3684 void
3685 bfin_hardware_loop (void)
3686 {
3687 cfun->machine->has_hardware_loops++;
3688 }
3689
3690 /* Maximum loop nesting depth. */
3691 #define MAX_LOOP_DEPTH 2
3692
3693 /* Maximum size of a loop. */
3694 #define MAX_LOOP_LENGTH 2042
3695
3696 /* Maximum distance of the LSETUP instruction from the loop start. */
3697 #define MAX_LSETUP_DISTANCE 30
3698
3699 /* We need to keep a vector of loops */
3700 typedef struct loop_info *loop_info;
3701 DEF_VEC_P (loop_info);
3702 DEF_VEC_ALLOC_P (loop_info,heap);
3703
3704 /* Information about a loop we have found (or are in the process of
3705 finding). */
3706 struct GTY (()) loop_info
3707 {
3708 /* loop number, for dumps */
3709 int loop_no;
3710
3711 /* All edges that jump into and out of the loop. */
3712 VEC(edge,gc) *incoming;
3713
3714 /* We can handle two cases: all incoming edges have the same destination
3715 block, or all incoming edges have the same source block. These two
3716 members are set to the common source or destination we found, or NULL
3717 if different blocks were found. If both are NULL the loop can't be
3718 optimized. */
3719 basic_block incoming_src;
3720 basic_block incoming_dest;
3721
3722 /* First block in the loop. This is the one branched to by the loop_end
3723 insn. */
3724 basic_block head;
3725
3726 /* Last block in the loop (the one with the loop_end insn). */
3727 basic_block tail;
3728
3729 /* The successor block of the loop. This is the one the loop_end insn
3730 falls into. */
3731 basic_block successor;
3732
3733 /* The last instruction in the tail. */
3734 rtx last_insn;
3735
3736 /* The loop_end insn. */
3737 rtx loop_end;
3738
3739 /* The iteration register. */
3740 rtx iter_reg;
3741
3742 /* The new label placed at the beginning of the loop. */
3743 rtx start_label;
3744
3745 /* The new label placed at the end of the loop. */
3746 rtx end_label;
3747
3748 /* The length of the loop. */
3749 int length;
3750
3751 /* The nesting depth of the loop. */
3752 int depth;
3753
3754 /* Nonzero if we can't optimize this loop. */
3755 int bad;
3756
3757 /* True if we have visited this loop. */
3758 int visited;
3759
3760 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3761 int clobber_loop0;
3762
3763 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3764 int clobber_loop1;
3765
3766 /* Next loop in the graph. */
3767 struct loop_info *next;
3768
3769 /* Immediate outer loop of this loop. */
3770 struct loop_info *outer;
3771
3772 /* Vector of blocks only within the loop, including those within
3773 inner loops. */
3774 VEC (basic_block,heap) *blocks;
3775
3776 /* Same information in a bitmap. */
3777 bitmap block_bitmap;
3778
3779 /* Vector of inner loops within this loop */
3780 VEC (loop_info,heap) *loops;
3781 };
3782
3783 static void
3784 bfin_dump_loops (loop_info loops)
3785 {
3786 loop_info loop;
3787
3788 for (loop = loops; loop; loop = loop->next)
3789 {
3790 loop_info i;
3791 basic_block b;
3792 unsigned ix;
3793
3794 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3795 if (loop->bad)
3796 fprintf (dump_file, "(bad) ");
3797 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3798
3799 fprintf (dump_file, " blocks: [ ");
3800 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3801 fprintf (dump_file, "%d ", b->index);
3802 fprintf (dump_file, "] ");
3803
3804 fprintf (dump_file, " inner loops: [ ");
3805 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3806 fprintf (dump_file, "%d ", i->loop_no);
3807 fprintf (dump_file, "]\n");
3808 }
3809 fprintf (dump_file, "\n");
3810 }
3811
3812 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3813 BB. Return true, if we find it. */
3814
3815 static bool
3816 bfin_bb_in_loop (loop_info loop, basic_block bb)
3817 {
3818 return bitmap_bit_p (loop->block_bitmap, bb->index);
3819 }
3820
3821 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3822 REG. Return true, if we find any. Don't count the loop's loop_end
3823 insn if it matches LOOP_END. */
3824
3825 static bool
3826 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3827 {
3828 unsigned ix;
3829 basic_block bb;
3830
3831 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3832 {
3833 rtx insn;
3834
3835 for (insn = BB_HEAD (bb);
3836 insn != NEXT_INSN (BB_END (bb));
3837 insn = NEXT_INSN (insn))
3838 {
3839 if (!INSN_P (insn))
3840 continue;
3841 if (insn == loop_end)
3842 continue;
3843 if (reg_mentioned_p (reg, PATTERN (insn)))
3844 return true;
3845 }
3846 }
3847 return false;
3848 }
3849
3850 /* Estimate the length of INSN conservatively. */
3851
3852 static int
3853 length_for_loop (rtx insn)
3854 {
3855 int length = 0;
3856 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3857 {
3858 if (ENABLE_WA_SPECULATIVE_SYNCS)
3859 length = 8;
3860 else if (ENABLE_WA_SPECULATIVE_LOADS)
3861 length = 6;
3862 }
3863 else if (LABEL_P (insn))
3864 {
3865 if (ENABLE_WA_SPECULATIVE_SYNCS)
3866 length = 4;
3867 }
3868
3869 if (NONDEBUG_INSN_P (insn))
3870 length += get_attr_length (insn);
3871
3872 return length;
3873 }
3874
3875 /* Optimize LOOP. */
3876
3877 static void
3878 bfin_optimize_loop (loop_info loop)
3879 {
3880 basic_block bb;
3881 loop_info inner;
3882 rtx insn, last_insn;
3883 rtx loop_init, start_label, end_label;
3884 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3885 rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
3886 rtx lc_reg, lt_reg, lb_reg;
3887 rtx seq, seq_end;
3888 int length;
3889 unsigned ix;
3890 int inner_depth = 0;
3891
3892 if (loop->visited)
3893 return;
3894
3895 loop->visited = 1;
3896
3897 if (loop->bad)
3898 {
3899 if (dump_file)
3900 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3901 goto bad_loop;
3902 }
3903
3904 /* Every loop contains in its list of inner loops every loop nested inside
3905 it, even if there are intermediate loops. This works because we're doing
3906 a depth-first search here and never visit a loop more than once. */
3907 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3908 {
3909 bfin_optimize_loop (inner);
3910
3911 if (!inner->bad && inner_depth < inner->depth)
3912 {
3913 inner_depth = inner->depth;
3914
3915 loop->clobber_loop0 |= inner->clobber_loop0;
3916 loop->clobber_loop1 |= inner->clobber_loop1;
3917 }
3918 }
3919
3920 loop->depth = inner_depth + 1;
3921 if (loop->depth > MAX_LOOP_DEPTH)
3922 {
3923 if (dump_file)
3924 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3925 goto bad_loop;
3926 }
3927
3928 /* Get the loop iteration register. */
3929 iter_reg = loop->iter_reg;
3930
3931 if (!REG_P (iter_reg))
3932 {
3933 if (dump_file)
3934 fprintf (dump_file, ";; loop %d iteration count not in a register\n",
3935 loop->loop_no);
3936 goto bad_loop;
3937 }
3938 scratchreg = NULL_RTX;
3939 scratch_init = iter_reg;
3940 scratch_init_insn = NULL_RTX;
3941 if (!PREG_P (iter_reg) && loop->incoming_src)
3942 {
3943 basic_block bb_in = loop->incoming_src;
3944 int i;
3945 for (i = REG_P0; i <= REG_P5; i++)
3946 if ((df_regs_ever_live_p (i)
3947 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3948 && call_used_regs[i]))
3949 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3950 {
3951 scratchreg = gen_rtx_REG (SImode, i);
3952 break;
3953 }
3954 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3955 insn = PREV_INSN (insn))
3956 {
3957 rtx set;
3958 if (NOTE_P (insn) || BARRIER_P (insn))
3959 continue;
3960 set = single_set (insn);
3961 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3962 {
3963 if (CONSTANT_P (SET_SRC (set)))
3964 {
3965 scratch_init = SET_SRC (set);
3966 scratch_init_insn = insn;
3967 }
3968 break;
3969 }
3970 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3971 break;
3972 }
3973 }
3974
3975 if (loop->incoming_src)
3976 {
3977 /* Make sure the predecessor is before the loop start label, as required by
3978 the LSETUP instruction. */
3979 length = 0;
3980 insn = BB_END (loop->incoming_src);
3981 /* If we have to insert the LSETUP before a jump, count that jump in the
3982 length. */
3983 if (VEC_length (edge, loop->incoming) > 1
3984 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3985 {
3986 gcc_assert (JUMP_P (insn));
3987 insn = PREV_INSN (insn);
3988 }
3989
3990 for (; insn && insn != loop->start_label; 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 lsetup not before loop_start\n",
3997 loop->loop_no);
3998 goto bad_loop;
3999 }
4000
4001 /* Account for the pop of a scratch register where necessary. */
4002 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
4003 && ENABLE_WA_LOAD_LCREGS)
4004 length += 2;
4005
4006 if (length > MAX_LSETUP_DISTANCE)
4007 {
4008 if (dump_file)
4009 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
4010 goto bad_loop;
4011 }
4012 }
4013
4014 /* Check if start_label appears before loop_end and calculate the
4015 offset between them. We calculate the length of instructions
4016 conservatively. */
4017 length = 0;
4018 for (insn = loop->start_label;
4019 insn && insn != loop->loop_end;
4020 insn = NEXT_INSN (insn))
4021 length += length_for_loop (insn);
4022
4023 if (!insn)
4024 {
4025 if (dump_file)
4026 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
4027 loop->loop_no);
4028 goto bad_loop;
4029 }
4030
4031 loop->length = length;
4032 if (loop->length > MAX_LOOP_LENGTH)
4033 {
4034 if (dump_file)
4035 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4036 goto bad_loop;
4037 }
4038
4039 /* Scan all the blocks to make sure they don't use iter_reg. */
4040 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
4041 {
4042 if (dump_file)
4043 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
4044 goto bad_loop;
4045 }
4046
4047 /* Scan all the insns to see if the loop body clobber
4048 any hardware loop registers. */
4049
4050 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
4051 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
4052 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
4053 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
4054 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
4055 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
4056
4057 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
4058 {
4059 rtx insn;
4060
4061 for (insn = BB_HEAD (bb);
4062 insn != NEXT_INSN (BB_END (bb));
4063 insn = NEXT_INSN (insn))
4064 {
4065 if (!INSN_P (insn))
4066 continue;
4067
4068 if (reg_set_p (reg_lc0, insn)
4069 || reg_set_p (reg_lt0, insn)
4070 || reg_set_p (reg_lb0, insn))
4071 loop->clobber_loop0 = 1;
4072
4073 if (reg_set_p (reg_lc1, insn)
4074 || reg_set_p (reg_lt1, insn)
4075 || reg_set_p (reg_lb1, insn))
4076 loop->clobber_loop1 |= 1;
4077 }
4078 }
4079
4080 if ((loop->clobber_loop0 && loop->clobber_loop1)
4081 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
4082 {
4083 loop->depth = MAX_LOOP_DEPTH + 1;
4084 if (dump_file)
4085 fprintf (dump_file, ";; loop %d no loop reg available\n",
4086 loop->loop_no);
4087 goto bad_loop;
4088 }
4089
4090 /* There should be an instruction before the loop_end instruction
4091 in the same basic block. And the instruction must not be
4092 - JUMP
4093 - CONDITIONAL BRANCH
4094 - CALL
4095 - CSYNC
4096 - SSYNC
4097 - Returns (RTS, RTN, etc.) */
4098
4099 bb = loop->tail;
4100 last_insn = find_prev_insn_start (loop->loop_end);
4101
4102 while (1)
4103 {
4104 for (; last_insn != BB_HEAD (bb);
4105 last_insn = find_prev_insn_start (last_insn))
4106 if (NONDEBUG_INSN_P (last_insn))
4107 break;
4108
4109 if (last_insn != BB_HEAD (bb))
4110 break;
4111
4112 if (single_pred_p (bb)
4113 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
4114 && single_pred (bb) != ENTRY_BLOCK_PTR)
4115 {
4116 bb = single_pred (bb);
4117 last_insn = BB_END (bb);
4118 continue;
4119 }
4120 else
4121 {
4122 last_insn = NULL_RTX;
4123 break;
4124 }
4125 }
4126
4127 if (!last_insn)
4128 {
4129 if (dump_file)
4130 fprintf (dump_file, ";; loop %d has no last instruction\n",
4131 loop->loop_no);
4132 goto bad_loop;
4133 }
4134
4135 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
4136 {
4137 if (dump_file)
4138 fprintf (dump_file, ";; loop %d has bad last instruction\n",
4139 loop->loop_no);
4140 goto bad_loop;
4141 }
4142 /* In all other cases, try to replace a bad last insn with a nop. */
4143 else if (JUMP_P (last_insn)
4144 || CALL_P (last_insn)
4145 || get_attr_type (last_insn) == TYPE_SYNC
4146 || get_attr_type (last_insn) == TYPE_CALL
4147 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
4148 || recog_memoized (last_insn) == CODE_FOR_return_internal
4149 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
4150 || asm_noperands (PATTERN (last_insn)) >= 0)
4151 {
4152 if (loop->length + 2 > MAX_LOOP_LENGTH)
4153 {
4154 if (dump_file)
4155 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4156 goto bad_loop;
4157 }
4158 if (dump_file)
4159 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
4160 loop->loop_no);
4161
4162 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
4163 }
4164
4165 loop->last_insn = last_insn;
4166
4167 /* The loop is good for replacement. */
4168 start_label = loop->start_label;
4169 end_label = gen_label_rtx ();
4170 iter_reg = loop->iter_reg;
4171
4172 if (loop->depth == 1 && !loop->clobber_loop1)
4173 {
4174 lc_reg = reg_lc1;
4175 lt_reg = reg_lt1;
4176 lb_reg = reg_lb1;
4177 loop->clobber_loop1 = 1;
4178 }
4179 else
4180 {
4181 lc_reg = reg_lc0;
4182 lt_reg = reg_lt0;
4183 lb_reg = reg_lb0;
4184 loop->clobber_loop0 = 1;
4185 }
4186
4187 loop->end_label = end_label;
4188
4189 /* Create a sequence containing the loop setup. */
4190 start_sequence ();
4191
4192 /* LSETUP only accepts P registers. If we have one, we can use it,
4193 otherwise there are several ways of working around the problem.
4194 If we're not affected by anomaly 312, we can load the LC register
4195 from any iteration register, and use LSETUP without initialization.
4196 If we've found a P scratch register that's not live here, we can
4197 instead copy the iter_reg into that and use an initializing LSETUP.
4198 If all else fails, push and pop P0 and use it as a scratch. */
4199 if (P_REGNO_P (REGNO (iter_reg)))
4200 {
4201 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4202 lb_reg, end_label,
4203 lc_reg, iter_reg);
4204 seq_end = emit_insn (loop_init);
4205 }
4206 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
4207 {
4208 emit_insn (gen_movsi (lc_reg, iter_reg));
4209 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
4210 lb_reg, end_label,
4211 lc_reg);
4212 seq_end = emit_insn (loop_init);
4213 }
4214 else if (scratchreg != NULL_RTX)
4215 {
4216 emit_insn (gen_movsi (scratchreg, scratch_init));
4217 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4218 lb_reg, end_label,
4219 lc_reg, scratchreg);
4220 seq_end = emit_insn (loop_init);
4221 if (scratch_init_insn != NULL_RTX)
4222 delete_insn (scratch_init_insn);
4223 }
4224 else
4225 {
4226 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
4227 rtx push = gen_frame_mem (SImode,
4228 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
4229 rtx pop = gen_frame_mem (SImode,
4230 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
4231 emit_insn (gen_movsi (push, p0reg));
4232 emit_insn (gen_movsi (p0reg, scratch_init));
4233 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4234 lb_reg, end_label,
4235 lc_reg, p0reg);
4236 emit_insn (loop_init);
4237 seq_end = emit_insn (gen_movsi (p0reg, pop));
4238 if (scratch_init_insn != NULL_RTX)
4239 delete_insn (scratch_init_insn);
4240 }
4241
4242 if (dump_file)
4243 {
4244 fprintf (dump_file, ";; replacing loop %d initializer with\n",
4245 loop->loop_no);
4246 print_rtl_single (dump_file, loop_init);
4247 fprintf (dump_file, ";; replacing loop %d terminator with\n",
4248 loop->loop_no);
4249 print_rtl_single (dump_file, loop->loop_end);
4250 }
4251
4252 /* If the loop isn't entered at the top, also create a jump to the entry
4253 point. */
4254 if (!loop->incoming_src && loop->head != loop->incoming_dest)
4255 {
4256 rtx label = BB_HEAD (loop->incoming_dest);
4257 /* If we're jumping to the final basic block in the loop, and there's
4258 only one cheap instruction before the end (typically an increment of
4259 an induction variable), we can just emit a copy here instead of a
4260 jump. */
4261 if (loop->incoming_dest == loop->tail
4262 && next_real_insn (label) == last_insn
4263 && asm_noperands (last_insn) < 0
4264 && GET_CODE (PATTERN (last_insn)) == SET)
4265 {
4266 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
4267 }
4268 else
4269 {
4270 emit_jump_insn (gen_jump (label));
4271 seq_end = emit_barrier ();
4272 }
4273 }
4274
4275 seq = get_insns ();
4276 end_sequence ();
4277
4278 if (loop->incoming_src)
4279 {
4280 rtx prev = BB_END (loop->incoming_src);
4281 if (VEC_length (edge, loop->incoming) > 1
4282 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
4283 {
4284 gcc_assert (JUMP_P (prev));
4285 prev = PREV_INSN (prev);
4286 }
4287 emit_insn_after (seq, prev);
4288 }
4289 else
4290 {
4291 basic_block new_bb;
4292 edge e;
4293 edge_iterator ei;
4294
4295 #ifdef ENABLE_CHECKING
4296 if (loop->head != loop->incoming_dest)
4297 {
4298 /* We aren't entering the loop at the top. Since we've established
4299 that the loop is entered only at one point, this means there
4300 can't be fallthru edges into the head. Any such fallthru edges
4301 would become invalid when we insert the new block, so verify
4302 that this does not in fact happen. */
4303 FOR_EACH_EDGE (e, ei, loop->head->preds)
4304 gcc_assert (!(e->flags & EDGE_FALLTHRU));
4305 }
4306 #endif
4307
4308 emit_insn_before (seq, BB_HEAD (loop->head));
4309 seq = emit_label_before (gen_label_rtx (), seq);
4310
4311 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
4312 FOR_EACH_EDGE (e, ei, loop->incoming)
4313 {
4314 if (!(e->flags & EDGE_FALLTHRU)
4315 || e->dest != loop->head)
4316 redirect_edge_and_branch_force (e, new_bb);
4317 else
4318 redirect_edge_succ (e, new_bb);
4319 }
4320 e = make_edge (new_bb, loop->head, 0);
4321 }
4322
4323 delete_insn (loop->loop_end);
4324 /* Insert the loop end label before the last instruction of the loop. */
4325 emit_label_before (loop->end_label, loop->last_insn);
4326
4327 return;
4328
4329 bad_loop:
4330
4331 if (dump_file)
4332 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
4333
4334 loop->bad = 1;
4335
4336 if (DPREG_P (loop->iter_reg))
4337 {
4338 /* If loop->iter_reg is a DREG or PREG, we can split it here
4339 without scratch register. */
4340 rtx insn, test;
4341
4342 emit_insn_before (gen_addsi3 (loop->iter_reg,
4343 loop->iter_reg,
4344 constm1_rtx),
4345 loop->loop_end);
4346
4347 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
4348 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
4349 loop->iter_reg, const0_rtx,
4350 loop->start_label),
4351 loop->loop_end);
4352
4353 JUMP_LABEL (insn) = loop->start_label;
4354 LABEL_NUSES (loop->start_label)++;
4355 delete_insn (loop->loop_end);
4356 }
4357 }
4358
4359 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
4360 a newly set up structure describing the loop, it is this function's
4361 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
4362 loop_end insn and its enclosing basic block. */
4363
4364 static void
4365 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
4366 {
4367 unsigned dwork = 0;
4368 basic_block bb;
4369 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
4370
4371 loop->tail = tail_bb;
4372 loop->head = BRANCH_EDGE (tail_bb)->dest;
4373 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
4374 loop->loop_end = tail_insn;
4375 loop->last_insn = NULL_RTX;
4376 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
4377 loop->depth = loop->length = 0;
4378 loop->visited = 0;
4379 loop->clobber_loop0 = loop->clobber_loop1 = 0;
4380 loop->outer = NULL;
4381 loop->loops = NULL;
4382 loop->incoming = VEC_alloc (edge, gc, 2);
4383 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
4384 loop->end_label = NULL_RTX;
4385 loop->bad = 0;
4386
4387 VEC_safe_push (basic_block, heap, works, loop->head);
4388
4389 while (VEC_iterate (basic_block, works, dwork++, bb))
4390 {
4391 edge e;
4392 edge_iterator ei;
4393 if (bb == EXIT_BLOCK_PTR)
4394 {
4395 /* We've reached the exit block. The loop must be bad. */
4396 if (dump_file)
4397 fprintf (dump_file,
4398 ";; Loop is bad - reached exit block while scanning\n");
4399 loop->bad = 1;
4400 break;
4401 }
4402
4403 if (bitmap_bit_p (loop->block_bitmap, bb->index))
4404 continue;
4405
4406 /* We've not seen this block before. Add it to the loop's
4407 list and then add each successor to the work list. */
4408
4409 VEC_safe_push (basic_block, heap, loop->blocks, bb);
4410 bitmap_set_bit (loop->block_bitmap, bb->index);
4411
4412 if (bb != tail_bb)
4413 {
4414 FOR_EACH_EDGE (e, ei, bb->succs)
4415 {
4416 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
4417 if (!REGNO_REG_SET_P (df_get_live_in (succ),
4418 REGNO (loop->iter_reg)))
4419 continue;
4420 if (!VEC_space (basic_block, works, 1))
4421 {
4422 if (dwork)
4423 {
4424 VEC_block_remove (basic_block, works, 0, dwork);
4425 dwork = 0;
4426 }
4427 else
4428 VEC_reserve (basic_block, heap, works, 1);
4429 }
4430 VEC_quick_push (basic_block, works, succ);
4431 }
4432 }
4433 }
4434
4435 /* Find the predecessor, and make sure nothing else jumps into this loop. */
4436 if (!loop->bad)
4437 {
4438 int pass, retry;
4439 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
4440 {
4441 edge e;
4442 edge_iterator ei;
4443 FOR_EACH_EDGE (e, ei, bb->preds)
4444 {
4445 basic_block pred = e->src;
4446
4447 if (!bfin_bb_in_loop (loop, pred))
4448 {
4449 if (dump_file)
4450 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
4451 loop->loop_no, pred->index,
4452 e->dest->index);
4453 VEC_safe_push (edge, gc, loop->incoming, e);
4454 }
4455 }
4456 }
4457
4458 for (pass = 0, retry = 1; retry && pass < 2; pass++)
4459 {
4460 edge e;
4461 edge_iterator ei;
4462 bool first = true;
4463 retry = 0;
4464
4465 FOR_EACH_EDGE (e, ei, loop->incoming)
4466 {
4467 if (first)
4468 {
4469 loop->incoming_src = e->src;
4470 loop->incoming_dest = e->dest;
4471 first = false;
4472 }
4473 else
4474 {
4475 if (e->dest != loop->incoming_dest)
4476 loop->incoming_dest = NULL;
4477 if (e->src != loop->incoming_src)
4478 loop->incoming_src = NULL;
4479 }
4480 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
4481 {
4482 if (pass == 0)
4483 {
4484 if (dump_file)
4485 fprintf (dump_file,
4486 ";; retrying loop %d with forwarder blocks\n",
4487 loop->loop_no);
4488 retry = 1;
4489 break;
4490 }
4491 loop->bad = 1;
4492 if (dump_file)
4493 fprintf (dump_file,
4494 ";; can't find suitable entry for loop %d\n",
4495 loop->loop_no);
4496 goto out;
4497 }
4498 }
4499 if (retry)
4500 {
4501 retry = 0;
4502 FOR_EACH_EDGE (e, ei, loop->incoming)
4503 {
4504 if (forwarder_block_p (e->src))
4505 {
4506 edge e2;
4507 edge_iterator ei2;
4508
4509 if (dump_file)
4510 fprintf (dump_file,
4511 ";; Adding forwarder block %d to loop %d and retrying\n",
4512 e->src->index, loop->loop_no);
4513 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
4514 bitmap_set_bit (loop->block_bitmap, e->src->index);
4515 FOR_EACH_EDGE (e2, ei2, e->src->preds)
4516 VEC_safe_push (edge, gc, loop->incoming, e2);
4517 VEC_unordered_remove (edge, loop->incoming, ei.index);
4518 retry = 1;
4519 break;
4520 }
4521 }
4522 if (!retry)
4523 {
4524 if (dump_file)
4525 fprintf (dump_file, ";; No forwarder blocks found\n");
4526 loop->bad = 1;
4527 }
4528 }
4529 }
4530 }
4531
4532 out:
4533 VEC_free (basic_block, heap, works);
4534 }
4535
4536 /* Analyze the structure of the loops in the current function. Use STACK
4537 for bitmap allocations. Returns all the valid candidates for hardware
4538 loops found in this function. */
4539 static loop_info
4540 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
4541 {
4542 loop_info loops = NULL;
4543 loop_info loop;
4544 basic_block bb;
4545 bitmap tmp_bitmap;
4546 int nloops = 0;
4547
4548 /* Find all the possible loop tails. This means searching for every
4549 loop_end instruction. For each one found, create a loop_info
4550 structure and add the head block to the work list. */
4551 FOR_EACH_BB (bb)
4552 {
4553 rtx tail = BB_END (bb);
4554
4555 while (GET_CODE (tail) == NOTE)
4556 tail = PREV_INSN (tail);
4557
4558 bb->aux = NULL;
4559
4560 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
4561 {
4562 rtx insn;
4563 /* A possible loop end */
4564
4565 /* There's a degenerate case we can handle - an empty loop consisting
4566 of only a back branch. Handle that by deleting the branch. */
4567 insn = BB_HEAD (BRANCH_EDGE (bb)->dest);
4568 if (next_real_insn (insn) == tail)
4569 {
4570 if (dump_file)
4571 {
4572 fprintf (dump_file, ";; degenerate loop ending at\n");
4573 print_rtl_single (dump_file, tail);
4574 }
4575 delete_insn_and_edges (tail);
4576 continue;
4577 }
4578
4579 loop = XNEW (struct loop_info);
4580 loop->next = loops;
4581 loops = loop;
4582 loop->loop_no = nloops++;
4583 loop->blocks = VEC_alloc (basic_block, heap, 20);
4584 loop->block_bitmap = BITMAP_ALLOC (stack);
4585 bb->aux = loop;
4586
4587 if (dump_file)
4588 {
4589 fprintf (dump_file, ";; potential loop %d ending at\n",
4590 loop->loop_no);
4591 print_rtl_single (dump_file, tail);
4592 }
4593
4594 bfin_discover_loop (loop, bb, tail);
4595 }
4596 }
4597
4598 tmp_bitmap = BITMAP_ALLOC (stack);
4599 /* Compute loop nestings. */
4600 for (loop = loops; loop; loop = loop->next)
4601 {
4602 loop_info other;
4603 if (loop->bad)
4604 continue;
4605
4606 for (other = loop->next; other; other = other->next)
4607 {
4608 if (other->bad)
4609 continue;
4610
4611 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
4612 if (bitmap_empty_p (tmp_bitmap))
4613 continue;
4614 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
4615 {
4616 other->outer = loop;
4617 VEC_safe_push (loop_info, heap, loop->loops, other);
4618 }
4619 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
4620 {
4621 loop->outer = other;
4622 VEC_safe_push (loop_info, heap, other->loops, loop);
4623 }
4624 else
4625 {
4626 if (dump_file)
4627 fprintf (dump_file,
4628 ";; can't find suitable nesting for loops %d and %d\n",
4629 loop->loop_no, other->loop_no);
4630 loop->bad = other->bad = 1;
4631 }
4632 }
4633 }
4634 BITMAP_FREE (tmp_bitmap);
4635
4636 return loops;
4637 }
4638
4639 /* Free up the loop structures in LOOPS. */
4640 static void
4641 free_loops (loop_info loops)
4642 {
4643 while (loops)
4644 {
4645 loop_info loop = loops;
4646 loops = loop->next;
4647 VEC_free (loop_info, heap, loop->loops);
4648 VEC_free (basic_block, heap, loop->blocks);
4649 BITMAP_FREE (loop->block_bitmap);
4650 XDELETE (loop);
4651 }
4652 }
4653
4654 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
4655
4656 /* The taken-branch edge from the loop end can actually go forward. Since the
4657 Blackfin's LSETUP instruction requires that the loop end be after the loop
4658 start, try to reorder a loop's basic blocks when we find such a case. */
4659 static void
4660 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4661 {
4662 basic_block bb;
4663 loop_info loop;
4664
4665 FOR_EACH_BB (bb)
4666 bb->aux = NULL;
4667 cfg_layout_initialize (0);
4668
4669 for (loop = loops; loop; loop = loop->next)
4670 {
4671 unsigned index;
4672 basic_block bb;
4673 edge e;
4674 edge_iterator ei;
4675
4676 if (loop->bad)
4677 continue;
4678
4679 /* Recreate an index for basic blocks that represents their order. */
4680 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4681 bb != EXIT_BLOCK_PTR;
4682 bb = bb->next_bb, index++)
4683 bb->aux = (PTR) index;
4684
4685 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4686 continue;
4687
4688 FOR_EACH_EDGE (e, ei, loop->head->succs)
4689 {
4690 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4691 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4692 {
4693 basic_block start_bb = e->dest;
4694 basic_block start_prev_bb = start_bb->prev_bb;
4695
4696 if (dump_file)
4697 fprintf (dump_file, ";; Moving block %d before block %d\n",
4698 loop->head->index, start_bb->index);
4699 loop->head->prev_bb->next_bb = loop->head->next_bb;
4700 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4701
4702 loop->head->prev_bb = start_prev_bb;
4703 loop->head->next_bb = start_bb;
4704 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4705 break;
4706 }
4707 }
4708 loops = loops->next;
4709 }
4710
4711 FOR_EACH_BB (bb)
4712 {
4713 if (bb->next_bb != EXIT_BLOCK_PTR)
4714 bb->aux = bb->next_bb;
4715 else
4716 bb->aux = NULL;
4717 }
4718 cfg_layout_finalize ();
4719 df_analyze ();
4720 }
4721
4722 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4723 and tries to rewrite the RTL of these loops so that proper Blackfin
4724 hardware loops are generated. */
4725
4726 static void
4727 bfin_reorg_loops (FILE *dump_file)
4728 {
4729 loop_info loops = NULL;
4730 loop_info loop;
4731 basic_block bb;
4732 bitmap_obstack stack;
4733
4734 bitmap_obstack_initialize (&stack);
4735
4736 if (dump_file)
4737 fprintf (dump_file, ";; Find loops, first pass\n\n");
4738
4739 loops = bfin_discover_loops (&stack, dump_file);
4740
4741 if (dump_file)
4742 bfin_dump_loops (loops);
4743
4744 bfin_reorder_loops (loops, dump_file);
4745 free_loops (loops);
4746
4747 if (dump_file)
4748 fprintf (dump_file, ";; Find loops, second pass\n\n");
4749
4750 loops = bfin_discover_loops (&stack, dump_file);
4751 if (dump_file)
4752 {
4753 fprintf (dump_file, ";; All loops found:\n\n");
4754 bfin_dump_loops (loops);
4755 }
4756
4757 /* Now apply the optimizations. */
4758 for (loop = loops; loop; loop = loop->next)
4759 bfin_optimize_loop (loop);
4760
4761 if (dump_file)
4762 {
4763 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4764 bfin_dump_loops (loops);
4765 }
4766
4767 free_loops (loops);
4768
4769 if (dump_file)
4770 print_rtl (dump_file, get_insns ());
4771
4772 FOR_EACH_BB (bb)
4773 bb->aux = NULL;
4774
4775 splitting_loops = 1;
4776 FOR_EACH_BB (bb)
4777 {
4778 rtx insn = BB_END (bb);
4779 if (!JUMP_P (insn))
4780 continue;
4781
4782 try_split (PATTERN (insn), insn, 1);
4783 }
4784 splitting_loops = 0;
4785 }
4786 \f
4787 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4788 Returns true if we modified the insn chain, false otherwise. */
4789 static bool
4790 gen_one_bundle (rtx slot[3])
4791 {
4792 gcc_assert (slot[1] != NULL_RTX);
4793
4794 /* Don't add extra NOPs if optimizing for size. */
4795 if (optimize_size
4796 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
4797 return false;
4798
4799 /* Verify that we really can do the multi-issue. */
4800 if (slot[0])
4801 {
4802 rtx t = NEXT_INSN (slot[0]);
4803 while (t != slot[1])
4804 {
4805 if (GET_CODE (t) != NOTE
4806 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4807 return false;
4808 t = NEXT_INSN (t);
4809 }
4810 }
4811 if (slot[2])
4812 {
4813 rtx t = NEXT_INSN (slot[1]);
4814 while (t != slot[2])
4815 {
4816 if (GET_CODE (t) != NOTE
4817 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4818 return false;
4819 t = NEXT_INSN (t);
4820 }
4821 }
4822
4823 if (slot[0] == NULL_RTX)
4824 {
4825 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4826 df_insn_rescan (slot[0]);
4827 }
4828 if (slot[2] == NULL_RTX)
4829 {
4830 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4831 df_insn_rescan (slot[2]);
4832 }
4833
4834 /* Avoid line number information being printed inside one bundle. */
4835 if (INSN_LOCATOR (slot[1])
4836 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4837 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4838 if (INSN_LOCATOR (slot[2])
4839 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4840 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4841
4842 /* Terminate them with "|| " instead of ";" in the output. */
4843 PUT_MODE (slot[0], SImode);
4844 PUT_MODE (slot[1], SImode);
4845 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4846 PUT_MODE (slot[2], QImode);
4847 return true;
4848 }
4849
4850 /* Go through all insns, and use the information generated during scheduling
4851 to generate SEQUENCEs to represent bundles of instructions issued
4852 simultaneously. */
4853
4854 static void
4855 bfin_gen_bundles (void)
4856 {
4857 basic_block bb;
4858 FOR_EACH_BB (bb)
4859 {
4860 rtx insn, next;
4861 rtx slot[3];
4862 int n_filled = 0;
4863
4864 slot[0] = slot[1] = slot[2] = NULL_RTX;
4865 for (insn = BB_HEAD (bb);; insn = next)
4866 {
4867 int at_end;
4868 rtx delete_this = NULL_RTX;
4869
4870 if (NONDEBUG_INSN_P (insn))
4871 {
4872 enum attr_type type = get_attr_type (insn);
4873
4874 if (type == TYPE_STALL)
4875 {
4876 gcc_assert (n_filled == 0);
4877 delete_this = insn;
4878 }
4879 else
4880 {
4881 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
4882 slot[0] = insn;
4883 else if (slot[1] == NULL_RTX)
4884 slot[1] = insn;
4885 else
4886 slot[2] = insn;
4887 n_filled++;
4888 }
4889 }
4890
4891 next = NEXT_INSN (insn);
4892 while (next && insn != BB_END (bb)
4893 && !(INSN_P (next)
4894 && GET_CODE (PATTERN (next)) != USE
4895 && GET_CODE (PATTERN (next)) != CLOBBER))
4896 {
4897 insn = next;
4898 next = NEXT_INSN (insn);
4899 }
4900
4901 /* BB_END can change due to emitting extra NOPs, so check here. */
4902 at_end = insn == BB_END (bb);
4903 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4904 {
4905 if ((n_filled < 2
4906 || !gen_one_bundle (slot))
4907 && slot[0] != NULL_RTX)
4908 {
4909 rtx pat = PATTERN (slot[0]);
4910 if (GET_CODE (pat) == SET
4911 && GET_CODE (SET_SRC (pat)) == UNSPEC
4912 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4913 {
4914 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4915 INSN_CODE (slot[0]) = -1;
4916 df_insn_rescan (slot[0]);
4917 }
4918 }
4919 n_filled = 0;
4920 slot[0] = slot[1] = slot[2] = NULL_RTX;
4921 }
4922 if (delete_this != NULL_RTX)
4923 delete_insn (delete_this);
4924 if (at_end)
4925 break;
4926 }
4927 }
4928 }
4929
4930 /* Ensure that no var tracking notes are emitted in the middle of a
4931 three-instruction bundle. */
4932
4933 static void
4934 reorder_var_tracking_notes (void)
4935 {
4936 basic_block bb;
4937 FOR_EACH_BB (bb)
4938 {
4939 rtx insn, next;
4940 rtx queue = NULL_RTX;
4941 bool in_bundle = false;
4942
4943 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4944 {
4945 next = NEXT_INSN (insn);
4946
4947 if (INSN_P (insn))
4948 {
4949 /* Emit queued up notes at the last instruction of a bundle. */
4950 if (GET_MODE (insn) == QImode)
4951 {
4952 while (queue)
4953 {
4954 rtx next_queue = PREV_INSN (queue);
4955 PREV_INSN (NEXT_INSN (insn)) = queue;
4956 NEXT_INSN (queue) = NEXT_INSN (insn);
4957 NEXT_INSN (insn) = queue;
4958 PREV_INSN (queue) = insn;
4959 queue = next_queue;
4960 }
4961 in_bundle = false;
4962 }
4963 else if (GET_MODE (insn) == SImode)
4964 in_bundle = true;
4965 }
4966 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4967 {
4968 if (in_bundle)
4969 {
4970 rtx prev = PREV_INSN (insn);
4971 PREV_INSN (next) = prev;
4972 NEXT_INSN (prev) = next;
4973
4974 PREV_INSN (insn) = queue;
4975 queue = insn;
4976 }
4977 }
4978 }
4979 }
4980 }
4981 \f
4982 /* On some silicon revisions, functions shorter than a certain number of cycles
4983 can cause unpredictable behaviour. Work around this by adding NOPs as
4984 needed. */
4985 static void
4986 workaround_rts_anomaly (void)
4987 {
4988 rtx insn, first_insn = NULL_RTX;
4989 int cycles = 4;
4990
4991 if (! ENABLE_WA_RETS)
4992 return;
4993
4994 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4995 {
4996 rtx pat;
4997
4998 if (BARRIER_P (insn))
4999 return;
5000
5001 if (NOTE_P (insn) || LABEL_P (insn))
5002 continue;
5003
5004 if (first_insn == NULL_RTX)
5005 first_insn = insn;
5006 pat = PATTERN (insn);
5007 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5008 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5009 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5010 continue;
5011
5012 if (CALL_P (insn))
5013 return;
5014
5015 if (JUMP_P (insn))
5016 {
5017 if (recog_memoized (insn) == CODE_FOR_return_internal)
5018 break;
5019
5020 /* Nothing to worry about for direct jumps. */
5021 if (!any_condjump_p (insn))
5022 return;
5023 if (cycles <= 1)
5024 return;
5025 cycles--;
5026 }
5027 else if (INSN_P (insn))
5028 {
5029 rtx pat = PATTERN (insn);
5030 int this_cycles = 1;
5031
5032 if (GET_CODE (pat) == PARALLEL)
5033 {
5034 if (push_multiple_operation (pat, VOIDmode)
5035 || pop_multiple_operation (pat, VOIDmode))
5036 this_cycles = n_regs_to_save;
5037 }
5038 else
5039 {
5040 enum insn_code icode = recog_memoized (insn);
5041 if (icode == CODE_FOR_link)
5042 this_cycles = 4;
5043 else if (icode == CODE_FOR_unlink)
5044 this_cycles = 3;
5045 else if (icode == CODE_FOR_mulsi3)
5046 this_cycles = 5;
5047 }
5048 if (this_cycles >= cycles)
5049 return;
5050
5051 cycles -= this_cycles;
5052 }
5053 }
5054 while (cycles > 0)
5055 {
5056 emit_insn_before (gen_nop (), first_insn);
5057 cycles--;
5058 }
5059 }
5060
5061 /* Return an insn type for INSN that can be used by the caller for anomaly
5062 workarounds. This differs from plain get_attr_type in that it handles
5063 SEQUENCEs. */
5064
5065 static enum attr_type
5066 type_for_anomaly (rtx insn)
5067 {
5068 rtx pat = PATTERN (insn);
5069 if (GET_CODE (pat) == SEQUENCE)
5070 {
5071 enum attr_type t;
5072 t = get_attr_type (XVECEXP (pat, 0, 1));
5073 if (t == TYPE_MCLD)
5074 return t;
5075 t = get_attr_type (XVECEXP (pat, 0, 2));
5076 if (t == TYPE_MCLD)
5077 return t;
5078 return TYPE_MCST;
5079 }
5080 else
5081 return get_attr_type (insn);
5082 }
5083
5084 /* Return true iff the address found in MEM is based on the register
5085 NP_REG and optionally has a positive offset. */
5086 static bool
5087 harmless_null_pointer_p (rtx mem, int np_reg)
5088 {
5089 mem = XEXP (mem, 0);
5090 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
5091 mem = XEXP (mem, 0);
5092 if (REG_P (mem) && REGNO (mem) == np_reg)
5093 return true;
5094 if (GET_CODE (mem) == PLUS
5095 && REG_P (XEXP (mem, 0)) && REGNO (XEXP (mem, 0)) == np_reg)
5096 {
5097 mem = XEXP (mem, 1);
5098 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
5099 return true;
5100 }
5101 return false;
5102 }
5103
5104 /* Return nonzero if INSN contains any loads that may trap. */
5105
5106 static bool
5107 trapping_loads_p (rtx insn, int np_reg, bool after_np_branch)
5108 {
5109 rtx pat = PATTERN (insn);
5110 rtx mem = SET_SRC (single_set (insn));
5111
5112 if (!after_np_branch)
5113 np_reg = -1;
5114 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
5115 && may_trap_p (mem));
5116 }
5117
5118 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
5119 a three-insn bundle, see if one of them is a load and return that if so.
5120 Return NULL_RTX if the insn does not contain loads. */
5121 static rtx
5122 find_load (rtx insn)
5123 {
5124 if (!NONDEBUG_INSN_P (insn))
5125 return NULL_RTX;
5126 if (get_attr_type (insn) == TYPE_MCLD)
5127 return insn;
5128 if (GET_MODE (insn) != SImode)
5129 return NULL_RTX;
5130 do {
5131 insn = NEXT_INSN (insn);
5132 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
5133 && get_attr_type (insn) == TYPE_MCLD)
5134 return insn;
5135 } while (GET_MODE (insn) != QImode);
5136 return NULL_RTX;
5137 }
5138
5139 /* Determine whether PAT is an indirect call pattern. */
5140 static bool
5141 indirect_call_p (rtx pat)
5142 {
5143 if (GET_CODE (pat) == PARALLEL)
5144 pat = XVECEXP (pat, 0, 0);
5145 if (GET_CODE (pat) == SET)
5146 pat = SET_SRC (pat);
5147 gcc_assert (GET_CODE (pat) == CALL);
5148 pat = XEXP (pat, 0);
5149 gcc_assert (GET_CODE (pat) == MEM);
5150 pat = XEXP (pat, 0);
5151
5152 return REG_P (pat);
5153 }
5154
5155 /* During workaround_speculation, track whether we're in the shadow of a
5156 conditional branch that tests a P register for NULL. If so, we can omit
5157 emitting NOPs if we see a load from that P register, since a speculative
5158 access at address 0 isn't a problem, and the load is executed in all other
5159 cases anyway.
5160 Global for communication with note_np_check_stores through note_stores.
5161 */
5162 int np_check_regno = -1;
5163 bool np_after_branch = false;
5164
5165 /* Subroutine of workaround_speculation, called through note_stores. */
5166 static void
5167 note_np_check_stores (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED)
5168 {
5169 if (REG_P (x) && (REGNO (x) == REG_CC || REGNO (x) == np_check_regno))
5170 np_check_regno = -1;
5171 }
5172
5173 static void
5174 workaround_speculation (void)
5175 {
5176 rtx insn, next;
5177 rtx last_condjump = NULL_RTX;
5178 int cycles_since_jump = INT_MAX;
5179 int delay_added = 0;
5180
5181 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5182 && ! ENABLE_WA_INDIRECT_CALLS)
5183 return;
5184
5185 /* First pass: find predicted-false branches; if something after them
5186 needs nops, insert them or change the branch to predict true. */
5187 for (insn = get_insns (); insn; insn = next)
5188 {
5189 rtx pat;
5190 int delay_needed = 0;
5191
5192 next = find_next_insn_start (insn);
5193
5194 if (NOTE_P (insn) || BARRIER_P (insn))
5195 continue;
5196
5197 if (LABEL_P (insn))
5198 {
5199 np_check_regno = -1;
5200 continue;
5201 }
5202
5203 pat = PATTERN (insn);
5204 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5205 || GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
5206 continue;
5207
5208 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
5209 {
5210 np_check_regno = -1;
5211 continue;
5212 }
5213
5214 if (JUMP_P (insn))
5215 {
5216 /* Is this a condjump based on a null pointer comparison we saw
5217 earlier? */
5218 if (np_check_regno != -1
5219 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
5220 {
5221 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
5222 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
5223 if (GET_CODE (op) == NE)
5224 np_after_branch = true;
5225 }
5226 if (any_condjump_p (insn)
5227 && ! cbranch_predicted_taken_p (insn))
5228 {
5229 last_condjump = insn;
5230 delay_added = 0;
5231 cycles_since_jump = 0;
5232 }
5233 else
5234 cycles_since_jump = INT_MAX;
5235 }
5236 else if (CALL_P (insn))
5237 {
5238 np_check_regno = -1;
5239 if (cycles_since_jump < INT_MAX)
5240 cycles_since_jump++;
5241 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
5242 {
5243 delay_needed = 3;
5244 }
5245 }
5246 else if (NONDEBUG_INSN_P (insn))
5247 {
5248 rtx load_insn = find_load (insn);
5249 enum attr_type type = type_for_anomaly (insn);
5250
5251 if (cycles_since_jump < INT_MAX)
5252 cycles_since_jump++;
5253
5254 /* Detect a comparison of a P register with zero. If we later
5255 see a condjump based on it, we have found a null pointer
5256 check. */
5257 if (recog_memoized (insn) == CODE_FOR_compare_eq)
5258 {
5259 rtx src = SET_SRC (PATTERN (insn));
5260 if (REG_P (XEXP (src, 0))
5261 && P_REGNO_P (REGNO (XEXP (src, 0)))
5262 && XEXP (src, 1) == const0_rtx)
5263 {
5264 np_check_regno = REGNO (XEXP (src, 0));
5265 np_after_branch = false;
5266 }
5267 else
5268 np_check_regno = -1;
5269 }
5270
5271 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5272 {
5273 if (trapping_loads_p (load_insn, np_check_regno,
5274 np_after_branch))
5275 delay_needed = 4;
5276 }
5277 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5278 delay_needed = 3;
5279
5280 /* See if we need to forget about a null pointer comparison
5281 we found earlier. */
5282 if (recog_memoized (insn) != CODE_FOR_compare_eq)
5283 {
5284 note_stores (PATTERN (insn), note_np_check_stores, NULL);
5285 if (np_check_regno != -1)
5286 {
5287 if (find_regno_note (insn, REG_INC, np_check_regno))
5288 np_check_regno = -1;
5289 }
5290 }
5291
5292 }
5293
5294 if (delay_needed > cycles_since_jump
5295 && (delay_needed - cycles_since_jump) > delay_added)
5296 {
5297 rtx pat1;
5298 int num_clobbers;
5299 rtx *op = recog_data.operand;
5300
5301 delay_needed -= cycles_since_jump;
5302
5303 extract_insn (last_condjump);
5304 if (optimize_size)
5305 {
5306 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
5307 op[3]);
5308 cycles_since_jump = INT_MAX;
5309 }
5310 else
5311 {
5312 /* Do not adjust cycles_since_jump in this case, so that
5313 we'll increase the number of NOPs for a subsequent insn
5314 if necessary. */
5315 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
5316 GEN_INT (delay_needed));
5317 delay_added = delay_needed;
5318 }
5319 PATTERN (last_condjump) = pat1;
5320 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
5321 }
5322 if (CALL_P (insn))
5323 {
5324 cycles_since_jump = INT_MAX;
5325 delay_added = 0;
5326 }
5327 }
5328
5329 /* Second pass: for predicted-true branches, see if anything at the
5330 branch destination needs extra nops. */
5331 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5332 {
5333 int cycles_since_jump;
5334 if (JUMP_P (insn)
5335 && any_condjump_p (insn)
5336 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
5337 || cbranch_predicted_taken_p (insn)))
5338 {
5339 rtx target = JUMP_LABEL (insn);
5340 rtx label = target;
5341 rtx next_tgt;
5342
5343 cycles_since_jump = 0;
5344 for (; target && cycles_since_jump < 3; target = next_tgt)
5345 {
5346 rtx pat;
5347
5348 next_tgt = find_next_insn_start (target);
5349
5350 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
5351 continue;
5352
5353 pat = PATTERN (target);
5354 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5355 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5356 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5357 continue;
5358
5359 if (NONDEBUG_INSN_P (target))
5360 {
5361 rtx load_insn = find_load (target);
5362 enum attr_type type = type_for_anomaly (target);
5363 int delay_needed = 0;
5364 if (cycles_since_jump < INT_MAX)
5365 cycles_since_jump++;
5366
5367 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5368 {
5369 if (trapping_loads_p (load_insn, -1, false))
5370 delay_needed = 2;
5371 }
5372 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5373 delay_needed = 2;
5374
5375 if (delay_needed > cycles_since_jump)
5376 {
5377 rtx prev = prev_real_insn (label);
5378 delay_needed -= cycles_since_jump;
5379 if (dump_file)
5380 fprintf (dump_file, "Adding %d nops after %d\n",
5381 delay_needed, INSN_UID (label));
5382 if (JUMP_P (prev)
5383 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
5384 {
5385 rtx x;
5386 HOST_WIDE_INT v;
5387
5388 if (dump_file)
5389 fprintf (dump_file,
5390 "Reducing nops on insn %d.\n",
5391 INSN_UID (prev));
5392 x = PATTERN (prev);
5393 x = XVECEXP (x, 0, 1);
5394 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
5395 XVECEXP (x, 0, 0) = GEN_INT (v);
5396 }
5397 while (delay_needed-- > 0)
5398 emit_insn_after (gen_nop (), label);
5399 break;
5400 }
5401 }
5402 }
5403 }
5404 }
5405 }
5406
5407 /* Called just before the final scheduling pass. If we need to insert NOPs
5408 later on to work around speculative loads, insert special placeholder
5409 insns that cause loads to be delayed for as many cycles as necessary
5410 (and possible). This reduces the number of NOPs we need to add.
5411 The dummy insns we generate are later removed by bfin_gen_bundles. */
5412 static void
5413 add_sched_insns_for_speculation (void)
5414 {
5415 rtx insn;
5416
5417 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5418 && ! ENABLE_WA_INDIRECT_CALLS)
5419 return;
5420
5421 /* First pass: find predicted-false branches; if something after them
5422 needs nops, insert them or change the branch to predict true. */
5423 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5424 {
5425 rtx pat;
5426
5427 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
5428 continue;
5429
5430 pat = PATTERN (insn);
5431 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5432 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5433 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5434 continue;
5435
5436 if (JUMP_P (insn))
5437 {
5438 if (any_condjump_p (insn)
5439 && !cbranch_predicted_taken_p (insn))
5440 {
5441 rtx n = next_real_insn (insn);
5442 emit_insn_before (gen_stall (GEN_INT (3)), n);
5443 }
5444 }
5445 }
5446
5447 /* Second pass: for predicted-true branches, see if anything at the
5448 branch destination needs extra nops. */
5449 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5450 {
5451 if (JUMP_P (insn)
5452 && any_condjump_p (insn)
5453 && (cbranch_predicted_taken_p (insn)))
5454 {
5455 rtx target = JUMP_LABEL (insn);
5456 rtx next = next_real_insn (target);
5457
5458 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
5459 && get_attr_type (next) == TYPE_STALL)
5460 continue;
5461 emit_insn_before (gen_stall (GEN_INT (1)), next);
5462 }
5463 }
5464 }
5465
5466 /* We use the machine specific reorg pass for emitting CSYNC instructions
5467 after conditional branches as needed.
5468
5469 The Blackfin is unusual in that a code sequence like
5470 if cc jump label
5471 r0 = (p0)
5472 may speculatively perform the load even if the condition isn't true. This
5473 happens for a branch that is predicted not taken, because the pipeline
5474 isn't flushed or stalled, so the early stages of the following instructions,
5475 which perform the memory reference, are allowed to execute before the
5476 jump condition is evaluated.
5477 Therefore, we must insert additional instructions in all places where this
5478 could lead to incorrect behavior. The manual recommends CSYNC, while
5479 VDSP seems to use NOPs (even though its corresponding compiler option is
5480 named CSYNC).
5481
5482 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
5483 When optimizing for size, we turn the branch into a predicted taken one.
5484 This may be slower due to mispredicts, but saves code size. */
5485
5486 static void
5487 bfin_reorg (void)
5488 {
5489 /* We are freeing block_for_insn in the toplev to keep compatibility
5490 with old MDEP_REORGS that are not CFG based. Recompute it now. */
5491 compute_bb_for_insn ();
5492
5493 if (bfin_flag_schedule_insns2)
5494 {
5495 splitting_for_sched = 1;
5496 split_all_insns ();
5497 splitting_for_sched = 0;
5498
5499 add_sched_insns_for_speculation ();
5500
5501 timevar_push (TV_SCHED2);
5502 if (flag_selective_scheduling2
5503 && !maybe_skip_selective_scheduling ())
5504 run_selective_scheduling ();
5505 else
5506 schedule_insns ();
5507 timevar_pop (TV_SCHED2);
5508
5509 /* Examine the schedule and insert nops as necessary for 64-bit parallel
5510 instructions. */
5511 bfin_gen_bundles ();
5512 }
5513
5514 df_analyze ();
5515
5516 /* Doloop optimization */
5517 if (cfun->machine->has_hardware_loops)
5518 bfin_reorg_loops (dump_file);
5519
5520 workaround_speculation ();
5521
5522 if (bfin_flag_var_tracking)
5523 {
5524 timevar_push (TV_VAR_TRACKING);
5525 variable_tracking_main ();
5526 reorder_var_tracking_notes ();
5527 timevar_pop (TV_VAR_TRACKING);
5528 }
5529
5530 df_finish_pass (false);
5531
5532 workaround_rts_anomaly ();
5533 }
5534 \f
5535 /* Handle interrupt_handler, exception_handler and nmi_handler function
5536 attributes; arguments as in struct attribute_spec.handler. */
5537
5538 static tree
5539 handle_int_attribute (tree *node, tree name,
5540 tree args ATTRIBUTE_UNUSED,
5541 int flags ATTRIBUTE_UNUSED,
5542 bool *no_add_attrs)
5543 {
5544 tree x = *node;
5545 if (TREE_CODE (x) == FUNCTION_DECL)
5546 x = TREE_TYPE (x);
5547
5548 if (TREE_CODE (x) != FUNCTION_TYPE)
5549 {
5550 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5551 name);
5552 *no_add_attrs = true;
5553 }
5554 else if (funkind (x) != SUBROUTINE)
5555 error ("multiple function type attributes specified");
5556
5557 return NULL_TREE;
5558 }
5559
5560 /* Return 0 if the attributes for two types are incompatible, 1 if they
5561 are compatible, and 2 if they are nearly compatible (which causes a
5562 warning to be generated). */
5563
5564 static int
5565 bfin_comp_type_attributes (const_tree type1, const_tree type2)
5566 {
5567 e_funkind kind1, kind2;
5568
5569 if (TREE_CODE (type1) != FUNCTION_TYPE)
5570 return 1;
5571
5572 kind1 = funkind (type1);
5573 kind2 = funkind (type2);
5574
5575 if (kind1 != kind2)
5576 return 0;
5577
5578 /* Check for mismatched modifiers */
5579 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
5580 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
5581 return 0;
5582
5583 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
5584 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
5585 return 0;
5586
5587 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
5588 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
5589 return 0;
5590
5591 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
5592 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
5593 return 0;
5594
5595 return 1;
5596 }
5597
5598 /* Handle a "longcall" or "shortcall" attribute; arguments as in
5599 struct attribute_spec.handler. */
5600
5601 static tree
5602 bfin_handle_longcall_attribute (tree *node, tree name,
5603 tree args ATTRIBUTE_UNUSED,
5604 int flags ATTRIBUTE_UNUSED,
5605 bool *no_add_attrs)
5606 {
5607 if (TREE_CODE (*node) != FUNCTION_TYPE
5608 && TREE_CODE (*node) != FIELD_DECL
5609 && TREE_CODE (*node) != TYPE_DECL)
5610 {
5611 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5612 name);
5613 *no_add_attrs = true;
5614 }
5615
5616 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
5617 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
5618 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
5619 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
5620 {
5621 warning (OPT_Wattributes,
5622 "can't apply both longcall and shortcall attributes to the same function");
5623 *no_add_attrs = true;
5624 }
5625
5626 return NULL_TREE;
5627 }
5628
5629 /* Handle a "l1_text" attribute; arguments as in
5630 struct attribute_spec.handler. */
5631
5632 static tree
5633 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5634 int ARG_UNUSED (flags), bool *no_add_attrs)
5635 {
5636 tree decl = *node;
5637
5638 if (TREE_CODE (decl) != FUNCTION_DECL)
5639 {
5640 error ("%qE attribute only applies to functions",
5641 name);
5642 *no_add_attrs = true;
5643 }
5644
5645 /* The decl may have already been given a section attribute
5646 from a previous declaration. Ensure they match. */
5647 else if (DECL_SECTION_NAME (decl) != NULL_TREE
5648 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5649 ".l1.text") != 0)
5650 {
5651 error ("section of %q+D conflicts with previous declaration",
5652 decl);
5653 *no_add_attrs = true;
5654 }
5655 else
5656 DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
5657
5658 return NULL_TREE;
5659 }
5660
5661 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
5662 arguments as in struct attribute_spec.handler. */
5663
5664 static tree
5665 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5666 int ARG_UNUSED (flags), bool *no_add_attrs)
5667 {
5668 tree decl = *node;
5669
5670 if (TREE_CODE (decl) != VAR_DECL)
5671 {
5672 error ("%qE attribute only applies to variables",
5673 name);
5674 *no_add_attrs = true;
5675 }
5676 else if (current_function_decl != NULL_TREE
5677 && !TREE_STATIC (decl))
5678 {
5679 error ("%qE attribute cannot be specified for local variables",
5680 name);
5681 *no_add_attrs = true;
5682 }
5683 else
5684 {
5685 const char *section_name;
5686
5687 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
5688 section_name = ".l1.data";
5689 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
5690 section_name = ".l1.data.A";
5691 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
5692 section_name = ".l1.data.B";
5693 else
5694 gcc_unreachable ();
5695
5696 /* The decl may have already been given a section attribute
5697 from a previous declaration. Ensure they match. */
5698 if (DECL_SECTION_NAME (decl) != NULL_TREE
5699 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5700 section_name) != 0)
5701 {
5702 error ("section of %q+D conflicts with previous declaration",
5703 decl);
5704 *no_add_attrs = true;
5705 }
5706 else
5707 DECL_SECTION_NAME (decl)
5708 = build_string (strlen (section_name) + 1, section_name);
5709 }
5710
5711 return NULL_TREE;
5712 }
5713
5714 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
5715
5716 static tree
5717 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
5718 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
5719 bool *no_add_attrs)
5720 {
5721 tree decl = *node;
5722
5723 if (TREE_CODE (decl) == FUNCTION_DECL)
5724 {
5725 if (DECL_SECTION_NAME (decl) != NULL_TREE
5726 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5727 ".l2.text") != 0)
5728 {
5729 error ("section of %q+D conflicts with previous declaration",
5730 decl);
5731 *no_add_attrs = true;
5732 }
5733 else
5734 DECL_SECTION_NAME (decl) = build_string (9, ".l2.text");
5735 }
5736 else if (TREE_CODE (decl) == VAR_DECL)
5737 {
5738 if (DECL_SECTION_NAME (decl) != NULL_TREE
5739 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5740 ".l2.data") != 0)
5741 {
5742 error ("section of %q+D conflicts with previous declaration",
5743 decl);
5744 *no_add_attrs = true;
5745 }
5746 else
5747 DECL_SECTION_NAME (decl) = build_string (9, ".l2.data");
5748 }
5749
5750 return NULL_TREE;
5751 }
5752
5753 /* Table of valid machine attributes. */
5754 static const struct attribute_spec bfin_attribute_table[] =
5755 {
5756 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
5757 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
5758 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
5759 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
5760 { "nesting", 0, 0, false, true, true, NULL },
5761 { "kspisusp", 0, 0, false, true, true, NULL },
5762 { "saveall", 0, 0, false, true, true, NULL },
5763 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
5764 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
5765 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute },
5766 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5767 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5768 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5769 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute },
5770 { NULL, 0, 0, false, false, false, NULL }
5771 };
5772 \f
5773 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
5774 tell the assembler to generate pointers to function descriptors in
5775 some cases. */
5776
5777 static bool
5778 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
5779 {
5780 if (TARGET_FDPIC && size == UNITS_PER_WORD)
5781 {
5782 if (GET_CODE (value) == SYMBOL_REF
5783 && SYMBOL_REF_FUNCTION_P (value))
5784 {
5785 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
5786 output_addr_const (asm_out_file, value);
5787 fputs (")\n", asm_out_file);
5788 return true;
5789 }
5790 if (!aligned_p)
5791 {
5792 /* We've set the unaligned SI op to NULL, so we always have to
5793 handle the unaligned case here. */
5794 assemble_integer_with_op ("\t.4byte\t", value);
5795 return true;
5796 }
5797 }
5798 return default_assemble_integer (value, size, aligned_p);
5799 }
5800 \f
5801 /* Output the assembler code for a thunk function. THUNK_DECL is the
5802 declaration for the thunk function itself, FUNCTION is the decl for
5803 the target function. DELTA is an immediate constant offset to be
5804 added to THIS. If VCALL_OFFSET is nonzero, the word at
5805 *(*this + vcall_offset) should be added to THIS. */
5806
5807 static void
5808 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
5809 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
5810 HOST_WIDE_INT vcall_offset, tree function)
5811 {
5812 rtx xops[3];
5813 /* The this parameter is passed as the first argument. */
5814 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
5815
5816 /* Adjust the this parameter by a fixed constant. */
5817 if (delta)
5818 {
5819 xops[1] = this_rtx;
5820 if (delta >= -64 && delta <= 63)
5821 {
5822 xops[0] = GEN_INT (delta);
5823 output_asm_insn ("%1 += %0;", xops);
5824 }
5825 else if (delta >= -128 && delta < -64)
5826 {
5827 xops[0] = GEN_INT (delta + 64);
5828 output_asm_insn ("%1 += -64; %1 += %0;", xops);
5829 }
5830 else if (delta > 63 && delta <= 126)
5831 {
5832 xops[0] = GEN_INT (delta - 63);
5833 output_asm_insn ("%1 += 63; %1 += %0;", xops);
5834 }
5835 else
5836 {
5837 xops[0] = GEN_INT (delta);
5838 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5839 }
5840 }
5841
5842 /* Adjust the this parameter by a value stored in the vtable. */
5843 if (vcall_offset)
5844 {
5845 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5846 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5847
5848 xops[1] = tmp;
5849 xops[2] = p2tmp;
5850 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5851
5852 /* Adjust the this parameter. */
5853 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
5854 if (!memory_operand (xops[0], Pmode))
5855 {
5856 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5857 xops[0] = GEN_INT (vcall_offset);
5858 xops[1] = tmp2;
5859 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5860 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5861 }
5862 xops[2] = this_rtx;
5863 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5864 }
5865
5866 xops[0] = XEXP (DECL_RTL (function), 0);
5867 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5868 output_asm_insn ("jump.l\t%P0", xops);
5869 }
5870 \f
5871 /* Codes for all the Blackfin builtins. */
5872 enum bfin_builtins
5873 {
5874 BFIN_BUILTIN_CSYNC,
5875 BFIN_BUILTIN_SSYNC,
5876 BFIN_BUILTIN_ONES,
5877 BFIN_BUILTIN_COMPOSE_2X16,
5878 BFIN_BUILTIN_EXTRACTLO,
5879 BFIN_BUILTIN_EXTRACTHI,
5880
5881 BFIN_BUILTIN_SSADD_2X16,
5882 BFIN_BUILTIN_SSSUB_2X16,
5883 BFIN_BUILTIN_SSADDSUB_2X16,
5884 BFIN_BUILTIN_SSSUBADD_2X16,
5885 BFIN_BUILTIN_MULT_2X16,
5886 BFIN_BUILTIN_MULTR_2X16,
5887 BFIN_BUILTIN_NEG_2X16,
5888 BFIN_BUILTIN_ABS_2X16,
5889 BFIN_BUILTIN_MIN_2X16,
5890 BFIN_BUILTIN_MAX_2X16,
5891
5892 BFIN_BUILTIN_SSADD_1X16,
5893 BFIN_BUILTIN_SSSUB_1X16,
5894 BFIN_BUILTIN_MULT_1X16,
5895 BFIN_BUILTIN_MULTR_1X16,
5896 BFIN_BUILTIN_NORM_1X16,
5897 BFIN_BUILTIN_NEG_1X16,
5898 BFIN_BUILTIN_ABS_1X16,
5899 BFIN_BUILTIN_MIN_1X16,
5900 BFIN_BUILTIN_MAX_1X16,
5901
5902 BFIN_BUILTIN_SUM_2X16,
5903 BFIN_BUILTIN_DIFFHL_2X16,
5904 BFIN_BUILTIN_DIFFLH_2X16,
5905
5906 BFIN_BUILTIN_SSADD_1X32,
5907 BFIN_BUILTIN_SSSUB_1X32,
5908 BFIN_BUILTIN_NORM_1X32,
5909 BFIN_BUILTIN_ROUND_1X32,
5910 BFIN_BUILTIN_NEG_1X32,
5911 BFIN_BUILTIN_ABS_1X32,
5912 BFIN_BUILTIN_MIN_1X32,
5913 BFIN_BUILTIN_MAX_1X32,
5914 BFIN_BUILTIN_MULT_1X32,
5915 BFIN_BUILTIN_MULT_1X32X32,
5916 BFIN_BUILTIN_MULT_1X32X32NS,
5917
5918 BFIN_BUILTIN_MULHISILL,
5919 BFIN_BUILTIN_MULHISILH,
5920 BFIN_BUILTIN_MULHISIHL,
5921 BFIN_BUILTIN_MULHISIHH,
5922
5923 BFIN_BUILTIN_LSHIFT_1X16,
5924 BFIN_BUILTIN_LSHIFT_2X16,
5925 BFIN_BUILTIN_SSASHIFT_1X16,
5926 BFIN_BUILTIN_SSASHIFT_2X16,
5927 BFIN_BUILTIN_SSASHIFT_1X32,
5928
5929 BFIN_BUILTIN_CPLX_MUL_16,
5930 BFIN_BUILTIN_CPLX_MAC_16,
5931 BFIN_BUILTIN_CPLX_MSU_16,
5932
5933 BFIN_BUILTIN_CPLX_MUL_16_S40,
5934 BFIN_BUILTIN_CPLX_MAC_16_S40,
5935 BFIN_BUILTIN_CPLX_MSU_16_S40,
5936
5937 BFIN_BUILTIN_CPLX_SQU,
5938
5939 BFIN_BUILTIN_LOADBYTES,
5940
5941 BFIN_BUILTIN_MAX
5942 };
5943
5944 #define def_builtin(NAME, TYPE, CODE) \
5945 do { \
5946 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5947 NULL, NULL_TREE); \
5948 } while (0)
5949
5950 /* Set up all builtin functions for this target. */
5951 static void
5952 bfin_init_builtins (void)
5953 {
5954 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5955 tree void_ftype_void
5956 = build_function_type (void_type_node, void_list_node);
5957 tree short_ftype_short
5958 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5959 NULL_TREE);
5960 tree short_ftype_int_int
5961 = build_function_type_list (short_integer_type_node, integer_type_node,
5962 integer_type_node, NULL_TREE);
5963 tree int_ftype_int_int
5964 = build_function_type_list (integer_type_node, integer_type_node,
5965 integer_type_node, NULL_TREE);
5966 tree int_ftype_int
5967 = build_function_type_list (integer_type_node, integer_type_node,
5968 NULL_TREE);
5969 tree short_ftype_int
5970 = build_function_type_list (short_integer_type_node, integer_type_node,
5971 NULL_TREE);
5972 tree int_ftype_v2hi_v2hi
5973 = build_function_type_list (integer_type_node, V2HI_type_node,
5974 V2HI_type_node, NULL_TREE);
5975 tree v2hi_ftype_v2hi_v2hi
5976 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5977 V2HI_type_node, NULL_TREE);
5978 tree v2hi_ftype_v2hi_v2hi_v2hi
5979 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5980 V2HI_type_node, V2HI_type_node, NULL_TREE);
5981 tree v2hi_ftype_int_int
5982 = build_function_type_list (V2HI_type_node, integer_type_node,
5983 integer_type_node, NULL_TREE);
5984 tree v2hi_ftype_v2hi_int
5985 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5986 integer_type_node, NULL_TREE);
5987 tree int_ftype_short_short
5988 = build_function_type_list (integer_type_node, short_integer_type_node,
5989 short_integer_type_node, NULL_TREE);
5990 tree v2hi_ftype_v2hi
5991 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5992 tree short_ftype_v2hi
5993 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5994 NULL_TREE);
5995 tree int_ftype_pint
5996 = build_function_type_list (integer_type_node,
5997 build_pointer_type (integer_type_node),
5998 NULL_TREE);
5999
6000 /* Add the remaining MMX insns with somewhat more complicated types. */
6001 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
6002 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
6003
6004 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
6005
6006 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
6007 BFIN_BUILTIN_COMPOSE_2X16);
6008 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
6009 BFIN_BUILTIN_EXTRACTHI);
6010 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
6011 BFIN_BUILTIN_EXTRACTLO);
6012
6013 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
6014 BFIN_BUILTIN_MIN_2X16);
6015 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
6016 BFIN_BUILTIN_MAX_2X16);
6017
6018 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
6019 BFIN_BUILTIN_SSADD_2X16);
6020 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
6021 BFIN_BUILTIN_SSSUB_2X16);
6022 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
6023 BFIN_BUILTIN_SSADDSUB_2X16);
6024 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
6025 BFIN_BUILTIN_SSSUBADD_2X16);
6026 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
6027 BFIN_BUILTIN_MULT_2X16);
6028 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
6029 BFIN_BUILTIN_MULTR_2X16);
6030 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
6031 BFIN_BUILTIN_NEG_2X16);
6032 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
6033 BFIN_BUILTIN_ABS_2X16);
6034
6035 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
6036 BFIN_BUILTIN_MIN_1X16);
6037 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
6038 BFIN_BUILTIN_MAX_1X16);
6039
6040 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
6041 BFIN_BUILTIN_SSADD_1X16);
6042 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
6043 BFIN_BUILTIN_SSSUB_1X16);
6044 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
6045 BFIN_BUILTIN_MULT_1X16);
6046 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
6047 BFIN_BUILTIN_MULTR_1X16);
6048 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
6049 BFIN_BUILTIN_NEG_1X16);
6050 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
6051 BFIN_BUILTIN_ABS_1X16);
6052 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
6053 BFIN_BUILTIN_NORM_1X16);
6054
6055 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
6056 BFIN_BUILTIN_SUM_2X16);
6057 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
6058 BFIN_BUILTIN_DIFFHL_2X16);
6059 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
6060 BFIN_BUILTIN_DIFFLH_2X16);
6061
6062 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
6063 BFIN_BUILTIN_MULHISILL);
6064 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
6065 BFIN_BUILTIN_MULHISIHL);
6066 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
6067 BFIN_BUILTIN_MULHISILH);
6068 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
6069 BFIN_BUILTIN_MULHISIHH);
6070
6071 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
6072 BFIN_BUILTIN_MIN_1X32);
6073 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
6074 BFIN_BUILTIN_MAX_1X32);
6075
6076 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
6077 BFIN_BUILTIN_SSADD_1X32);
6078 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
6079 BFIN_BUILTIN_SSSUB_1X32);
6080 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
6081 BFIN_BUILTIN_NEG_1X32);
6082 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
6083 BFIN_BUILTIN_ABS_1X32);
6084 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
6085 BFIN_BUILTIN_NORM_1X32);
6086 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
6087 BFIN_BUILTIN_ROUND_1X32);
6088 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
6089 BFIN_BUILTIN_MULT_1X32);
6090 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
6091 BFIN_BUILTIN_MULT_1X32X32);
6092 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
6093 BFIN_BUILTIN_MULT_1X32X32NS);
6094
6095 /* Shifts. */
6096 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
6097 BFIN_BUILTIN_SSASHIFT_1X16);
6098 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
6099 BFIN_BUILTIN_SSASHIFT_2X16);
6100 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
6101 BFIN_BUILTIN_LSHIFT_1X16);
6102 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
6103 BFIN_BUILTIN_LSHIFT_2X16);
6104 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
6105 BFIN_BUILTIN_SSASHIFT_1X32);
6106
6107 /* Complex numbers. */
6108 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
6109 BFIN_BUILTIN_SSADD_2X16);
6110 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
6111 BFIN_BUILTIN_SSSUB_2X16);
6112 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
6113 BFIN_BUILTIN_CPLX_MUL_16);
6114 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
6115 BFIN_BUILTIN_CPLX_MAC_16);
6116 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
6117 BFIN_BUILTIN_CPLX_MSU_16);
6118 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
6119 BFIN_BUILTIN_CPLX_MUL_16_S40);
6120 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
6121 BFIN_BUILTIN_CPLX_MAC_16_S40);
6122 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
6123 BFIN_BUILTIN_CPLX_MSU_16_S40);
6124 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
6125 BFIN_BUILTIN_CPLX_SQU);
6126
6127 /* "Unaligned" load. */
6128 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
6129 BFIN_BUILTIN_LOADBYTES);
6130
6131 }
6132
6133
6134 struct builtin_description
6135 {
6136 const enum insn_code icode;
6137 const char *const name;
6138 const enum bfin_builtins code;
6139 int macflag;
6140 };
6141
6142 static const struct builtin_description bdesc_2arg[] =
6143 {
6144 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
6145
6146 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
6147 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
6148 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
6149 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
6150 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
6151
6152 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
6153 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
6154 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
6155 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
6156
6157 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
6158 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
6159 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
6160 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
6161
6162 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
6163 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
6164 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
6165 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
6166 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
6167 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
6168
6169 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
6170 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
6171 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
6172 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
6173 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
6174
6175 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
6176 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
6177 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
6178 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
6179
6180 };
6181
6182 static const struct builtin_description bdesc_1arg[] =
6183 {
6184 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
6185
6186 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
6187
6188 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
6189 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
6190 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
6191
6192 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
6193 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
6194 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
6195 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
6196
6197 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
6198 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
6199 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
6200 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
6201 };
6202
6203 /* Errors in the source file can cause expand_expr to return const0_rtx
6204 where we expect a vector. To avoid crashing, use one of the vector
6205 clear instructions. */
6206 static rtx
6207 safe_vector_operand (rtx x, enum machine_mode mode)
6208 {
6209 if (x != const0_rtx)
6210 return x;
6211 x = gen_reg_rtx (SImode);
6212
6213 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
6214 return gen_lowpart (mode, x);
6215 }
6216
6217 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
6218 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
6219
6220 static rtx
6221 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
6222 int macflag)
6223 {
6224 rtx pat;
6225 tree arg0 = CALL_EXPR_ARG (exp, 0);
6226 tree arg1 = CALL_EXPR_ARG (exp, 1);
6227 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6228 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6229 enum machine_mode op0mode = GET_MODE (op0);
6230 enum machine_mode op1mode = GET_MODE (op1);
6231 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6232 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6233 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
6234
6235 if (VECTOR_MODE_P (mode0))
6236 op0 = safe_vector_operand (op0, mode0);
6237 if (VECTOR_MODE_P (mode1))
6238 op1 = safe_vector_operand (op1, mode1);
6239
6240 if (! target
6241 || GET_MODE (target) != tmode
6242 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6243 target = gen_reg_rtx (tmode);
6244
6245 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
6246 {
6247 op0mode = HImode;
6248 op0 = gen_lowpart (HImode, op0);
6249 }
6250 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
6251 {
6252 op1mode = HImode;
6253 op1 = gen_lowpart (HImode, op1);
6254 }
6255 /* In case the insn wants input operands in modes different from
6256 the result, abort. */
6257 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
6258 && (op1mode == mode1 || op1mode == VOIDmode));
6259
6260 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6261 op0 = copy_to_mode_reg (mode0, op0);
6262 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6263 op1 = copy_to_mode_reg (mode1, op1);
6264
6265 if (macflag == -1)
6266 pat = GEN_FCN (icode) (target, op0, op1);
6267 else
6268 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
6269 if (! pat)
6270 return 0;
6271
6272 emit_insn (pat);
6273 return target;
6274 }
6275
6276 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
6277
6278 static rtx
6279 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
6280 rtx target)
6281 {
6282 rtx pat;
6283 tree arg0 = CALL_EXPR_ARG (exp, 0);
6284 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6285 enum machine_mode op0mode = GET_MODE (op0);
6286 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6287 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6288
6289 if (! target
6290 || GET_MODE (target) != tmode
6291 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6292 target = gen_reg_rtx (tmode);
6293
6294 if (VECTOR_MODE_P (mode0))
6295 op0 = safe_vector_operand (op0, mode0);
6296
6297 if (op0mode == SImode && mode0 == HImode)
6298 {
6299 op0mode = HImode;
6300 op0 = gen_lowpart (HImode, op0);
6301 }
6302 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
6303
6304 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6305 op0 = copy_to_mode_reg (mode0, op0);
6306
6307 pat = GEN_FCN (icode) (target, op0);
6308 if (! pat)
6309 return 0;
6310 emit_insn (pat);
6311 return target;
6312 }
6313
6314 /* Expand an expression EXP that calls a built-in function,
6315 with result going to TARGET if that's convenient
6316 (and in mode MODE if that's convenient).
6317 SUBTARGET may be used as the target for computing one of EXP's operands.
6318 IGNORE is nonzero if the value is to be ignored. */
6319
6320 static rtx
6321 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6322 rtx subtarget ATTRIBUTE_UNUSED,
6323 enum machine_mode mode ATTRIBUTE_UNUSED,
6324 int ignore ATTRIBUTE_UNUSED)
6325 {
6326 size_t i;
6327 enum insn_code icode;
6328 const struct builtin_description *d;
6329 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6330 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6331 tree arg0, arg1, arg2;
6332 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
6333 enum machine_mode tmode, mode0;
6334
6335 switch (fcode)
6336 {
6337 case BFIN_BUILTIN_CSYNC:
6338 emit_insn (gen_csync ());
6339 return 0;
6340 case BFIN_BUILTIN_SSYNC:
6341 emit_insn (gen_ssync ());
6342 return 0;
6343
6344 case BFIN_BUILTIN_DIFFHL_2X16:
6345 case BFIN_BUILTIN_DIFFLH_2X16:
6346 case BFIN_BUILTIN_SUM_2X16:
6347 arg0 = CALL_EXPR_ARG (exp, 0);
6348 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6349 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
6350 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
6351 : CODE_FOR_ssaddhilov2hi3);
6352 tmode = insn_data[icode].operand[0].mode;
6353 mode0 = insn_data[icode].operand[1].mode;
6354
6355 if (! target
6356 || GET_MODE (target) != tmode
6357 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6358 target = gen_reg_rtx (tmode);
6359
6360 if (VECTOR_MODE_P (mode0))
6361 op0 = safe_vector_operand (op0, mode0);
6362
6363 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6364 op0 = copy_to_mode_reg (mode0, op0);
6365
6366 pat = GEN_FCN (icode) (target, op0, op0);
6367 if (! pat)
6368 return 0;
6369 emit_insn (pat);
6370 return target;
6371
6372 case BFIN_BUILTIN_MULT_1X32X32:
6373 case BFIN_BUILTIN_MULT_1X32X32NS:
6374 arg0 = CALL_EXPR_ARG (exp, 0);
6375 arg1 = CALL_EXPR_ARG (exp, 1);
6376 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6377 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6378 if (! target
6379 || !register_operand (target, SImode))
6380 target = gen_reg_rtx (SImode);
6381 if (! register_operand (op0, SImode))
6382 op0 = copy_to_mode_reg (SImode, op0);
6383 if (! register_operand (op1, SImode))
6384 op1 = copy_to_mode_reg (SImode, op1);
6385
6386 a1reg = gen_rtx_REG (PDImode, REG_A1);
6387 a0reg = gen_rtx_REG (PDImode, REG_A0);
6388 tmp1 = gen_lowpart (V2HImode, op0);
6389 tmp2 = gen_lowpart (V2HImode, op1);
6390 emit_insn (gen_flag_macinit1hi (a1reg,
6391 gen_lowpart (HImode, op0),
6392 gen_lowpart (HImode, op1),
6393 GEN_INT (MACFLAG_FU)));
6394 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
6395
6396 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
6397 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
6398 const1_rtx, const1_rtx,
6399 const1_rtx, const0_rtx, a1reg,
6400 const0_rtx, GEN_INT (MACFLAG_NONE),
6401 GEN_INT (MACFLAG_M)));
6402 else
6403 {
6404 /* For saturating multiplication, there's exactly one special case
6405 to be handled: multiplying the smallest negative value with
6406 itself. Due to shift correction in fractional multiplies, this
6407 can overflow. Iff this happens, OP2 will contain 1, which, when
6408 added in 32 bits to the smallest negative, wraps to the largest
6409 positive, which is the result we want. */
6410 op2 = gen_reg_rtx (V2HImode);
6411 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
6412 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
6413 gen_lowpart (SImode, op2)));
6414 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
6415 const1_rtx, const1_rtx,
6416 const1_rtx, const0_rtx, a1reg,
6417 const0_rtx, GEN_INT (MACFLAG_NONE),
6418 GEN_INT (MACFLAG_M)));
6419 op2 = gen_reg_rtx (SImode);
6420 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
6421 }
6422 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
6423 const1_rtx, const0_rtx,
6424 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
6425 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
6426 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
6427 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
6428 emit_insn (gen_addsi3 (target, target, op2));
6429 return target;
6430
6431 case BFIN_BUILTIN_CPLX_MUL_16:
6432 case BFIN_BUILTIN_CPLX_MUL_16_S40:
6433 arg0 = CALL_EXPR_ARG (exp, 0);
6434 arg1 = CALL_EXPR_ARG (exp, 1);
6435 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6436 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6437 accvec = gen_reg_rtx (V2PDImode);
6438 icode = CODE_FOR_flag_macv2hi_parts;
6439
6440 if (! target
6441 || GET_MODE (target) != V2HImode
6442 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6443 target = gen_reg_rtx (tmode);
6444 if (! register_operand (op0, GET_MODE (op0)))
6445 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6446 if (! register_operand (op1, GET_MODE (op1)))
6447 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6448
6449 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
6450 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6451 const0_rtx, const0_rtx,
6452 const1_rtx, GEN_INT (MACFLAG_W32)));
6453 else
6454 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6455 const0_rtx, const0_rtx,
6456 const1_rtx, GEN_INT (MACFLAG_NONE)));
6457 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
6458 const1_rtx, const1_rtx,
6459 const0_rtx, accvec, const1_rtx, const0_rtx,
6460 GEN_INT (MACFLAG_NONE), accvec));
6461
6462 return target;
6463
6464 case BFIN_BUILTIN_CPLX_MAC_16:
6465 case BFIN_BUILTIN_CPLX_MSU_16:
6466 case BFIN_BUILTIN_CPLX_MAC_16_S40:
6467 case BFIN_BUILTIN_CPLX_MSU_16_S40:
6468 arg0 = CALL_EXPR_ARG (exp, 0);
6469 arg1 = CALL_EXPR_ARG (exp, 1);
6470 arg2 = CALL_EXPR_ARG (exp, 2);
6471 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6472 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6473 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
6474 accvec = gen_reg_rtx (V2PDImode);
6475 icode = CODE_FOR_flag_macv2hi_parts;
6476
6477 if (! target
6478 || GET_MODE (target) != V2HImode
6479 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6480 target = gen_reg_rtx (tmode);
6481 if (! register_operand (op1, GET_MODE (op1)))
6482 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6483 if (! register_operand (op2, GET_MODE (op2)))
6484 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
6485
6486 tmp1 = gen_reg_rtx (SImode);
6487 tmp2 = gen_reg_rtx (SImode);
6488 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
6489 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
6490 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
6491 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
6492 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6493 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
6494 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6495 const0_rtx, const0_rtx,
6496 const1_rtx, accvec, const0_rtx,
6497 const0_rtx,
6498 GEN_INT (MACFLAG_W32)));
6499 else
6500 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6501 const0_rtx, const0_rtx,
6502 const1_rtx, accvec, const0_rtx,
6503 const0_rtx,
6504 GEN_INT (MACFLAG_NONE)));
6505 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6506 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
6507 {
6508 tmp1 = const1_rtx;
6509 tmp2 = const0_rtx;
6510 }
6511 else
6512 {
6513 tmp1 = const0_rtx;
6514 tmp2 = const1_rtx;
6515 }
6516 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
6517 const1_rtx, const1_rtx,
6518 const0_rtx, accvec, tmp1, tmp2,
6519 GEN_INT (MACFLAG_NONE), accvec));
6520
6521 return target;
6522
6523 case BFIN_BUILTIN_CPLX_SQU:
6524 arg0 = CALL_EXPR_ARG (exp, 0);
6525 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6526 accvec = gen_reg_rtx (V2PDImode);
6527 icode = CODE_FOR_flag_mulv2hi;
6528 tmp1 = gen_reg_rtx (V2HImode);
6529 tmp2 = gen_reg_rtx (V2HImode);
6530
6531 if (! target
6532 || GET_MODE (target) != V2HImode
6533 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6534 target = gen_reg_rtx (V2HImode);
6535 if (! register_operand (op0, GET_MODE (op0)))
6536 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6537
6538 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
6539
6540 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
6541 const0_rtx, const1_rtx,
6542 GEN_INT (MACFLAG_NONE)));
6543
6544 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
6545 const0_rtx));
6546 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
6547 const0_rtx, const1_rtx));
6548
6549 return target;
6550
6551 default:
6552 break;
6553 }
6554
6555 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6556 if (d->code == fcode)
6557 return bfin_expand_binop_builtin (d->icode, exp, target,
6558 d->macflag);
6559
6560 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6561 if (d->code == fcode)
6562 return bfin_expand_unop_builtin (d->icode, exp, target);
6563
6564 gcc_unreachable ();
6565 }
6566 \f
6567 #undef TARGET_INIT_BUILTINS
6568 #define TARGET_INIT_BUILTINS bfin_init_builtins
6569
6570 #undef TARGET_EXPAND_BUILTIN
6571 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
6572
6573 #undef TARGET_ASM_GLOBALIZE_LABEL
6574 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
6575
6576 #undef TARGET_ASM_FILE_START
6577 #define TARGET_ASM_FILE_START output_file_start
6578
6579 #undef TARGET_ATTRIBUTE_TABLE
6580 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
6581
6582 #undef TARGET_COMP_TYPE_ATTRIBUTES
6583 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
6584
6585 #undef TARGET_RTX_COSTS
6586 #define TARGET_RTX_COSTS bfin_rtx_costs
6587
6588 #undef TARGET_ADDRESS_COST
6589 #define TARGET_ADDRESS_COST bfin_address_cost
6590
6591 #undef TARGET_ASM_INTEGER
6592 #define TARGET_ASM_INTEGER bfin_assemble_integer
6593
6594 #undef TARGET_MACHINE_DEPENDENT_REORG
6595 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
6596
6597 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6598 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
6599
6600 #undef TARGET_ASM_OUTPUT_MI_THUNK
6601 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
6602 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6603 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
6604
6605 #undef TARGET_SCHED_ADJUST_COST
6606 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
6607
6608 #undef TARGET_SCHED_ISSUE_RATE
6609 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
6610
6611 #undef TARGET_PROMOTE_FUNCTION_MODE
6612 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
6613
6614 #undef TARGET_ARG_PARTIAL_BYTES
6615 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
6616
6617 #undef TARGET_PASS_BY_REFERENCE
6618 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
6619
6620 #undef TARGET_SETUP_INCOMING_VARARGS
6621 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
6622
6623 #undef TARGET_STRUCT_VALUE_RTX
6624 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
6625
6626 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6627 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
6628
6629 #undef TARGET_HANDLE_OPTION
6630 #define TARGET_HANDLE_OPTION bfin_handle_option
6631
6632 #undef TARGET_DEFAULT_TARGET_FLAGS
6633 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
6634
6635 #undef TARGET_SECONDARY_RELOAD
6636 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
6637
6638 #undef TARGET_DELEGITIMIZE_ADDRESS
6639 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
6640
6641 #undef TARGET_CANNOT_FORCE_CONST_MEM
6642 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
6643
6644 #undef TARGET_RETURN_IN_MEMORY
6645 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
6646
6647 #undef TARGET_LEGITIMATE_ADDRESS_P
6648 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
6649
6650 #undef TARGET_FRAME_POINTER_REQUIRED
6651 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
6652
6653 #undef TARGET_CAN_ELIMINATE
6654 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
6655
6656 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
6657 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
6658 #undef TARGET_TRAMPOLINE_INIT
6659 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
6660
6661 struct gcc_target targetm = TARGET_INITIALIZER;