]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/mep/mep.c
Update Copyright years for files modified in 2011 and/or 2012.
[thirdparty/gcc.git] / gcc / config / mep / mep.c
1 /* Definitions for Toshiba Media Processor
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011, 2012
4 Free Software Foundation, Inc.
5 Contributed by Red Hat, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "tree.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "recog.h"
38 #include "obstack.h"
39 #include "tree.h"
40 #include "expr.h"
41 #include "except.h"
42 #include "function.h"
43 #include "optabs.h"
44 #include "reload.h"
45 #include "tm_p.h"
46 #include "ggc.h"
47 #include "diagnostic-core.h"
48 #include "target.h"
49 #include "target-def.h"
50 #include "langhooks.h"
51 #include "df.h"
52 #include "gimple.h"
53 #include "opts.h"
54 #include "dumpfile.h"
55
56 /* Structure of this file:
57
58 + Command Line Option Support
59 + Pattern support - constraints, predicates, expanders
60 + Reload Support
61 + Costs
62 + Functions to save and restore machine-specific function data.
63 + Frame/Epilog/Prolog Related
64 + Operand Printing
65 + Function args in registers
66 + Handle pipeline hazards
67 + Handle attributes
68 + Trampolines
69 + Machine-dependent Reorg
70 + Builtins. */
71
72 /* Symbol encodings:
73
74 Symbols are encoded as @ <char> . <name> where <char> is one of these:
75
76 b - based
77 t - tiny
78 n - near
79 f - far
80 i - io, near
81 I - io, far
82 c - cb (control bus) */
83
84 struct GTY(()) machine_function
85 {
86 int mep_frame_pointer_needed;
87
88 /* For varargs. */
89 int arg_regs_to_save;
90 int regsave_filler;
91 int frame_filler;
92 int frame_locked;
93
94 /* Records __builtin_return address. */
95 rtx eh_stack_adjust;
96
97 int reg_save_size;
98 int reg_save_slot[FIRST_PSEUDO_REGISTER];
99 unsigned char reg_saved[FIRST_PSEUDO_REGISTER];
100
101 /* 2 if the current function has an interrupt attribute, 1 if not, 0
102 if unknown. This is here because resource.c uses EPILOGUE_USES
103 which needs it. */
104 int interrupt_handler;
105
106 /* Likewise, for disinterrupt attribute. */
107 int disable_interrupts;
108
109 /* Number of doloop tags used so far. */
110 int doloop_tags;
111
112 /* True if the last tag was allocated to a doloop_end. */
113 bool doloop_tag_from_end;
114
115 /* True if reload changes $TP. */
116 bool reload_changes_tp;
117
118 /* 2 if there are asm()s without operands, 1 if not, 0 if unknown.
119 We only set this if the function is an interrupt handler. */
120 int asms_without_operands;
121 };
122
123 #define MEP_CONTROL_REG(x) \
124 (GET_CODE (x) == REG && ANY_CONTROL_REGNO_P (REGNO (x)))
125
126 static GTY(()) section * based_section;
127 static GTY(()) section * tinybss_section;
128 static GTY(()) section * far_section;
129 static GTY(()) section * farbss_section;
130 static GTY(()) section * frodata_section;
131 static GTY(()) section * srodata_section;
132
133 static GTY(()) section * vtext_section;
134 static GTY(()) section * vftext_section;
135 static GTY(()) section * ftext_section;
136
137 static void mep_set_leaf_registers (int);
138 static bool symbol_p (rtx);
139 static bool symbolref_p (rtx);
140 static void encode_pattern_1 (rtx);
141 static void encode_pattern (rtx);
142 static bool const_in_range (rtx, int, int);
143 static void mep_rewrite_mult (rtx, rtx);
144 static void mep_rewrite_mulsi3 (rtx, rtx, rtx, rtx);
145 static void mep_rewrite_maddsi3 (rtx, rtx, rtx, rtx, rtx);
146 static bool mep_reuse_lo_p_1 (rtx, rtx, rtx, bool);
147 static bool move_needs_splitting (rtx, rtx, enum machine_mode);
148 static bool mep_expand_setcc_1 (enum rtx_code, rtx, rtx, rtx);
149 static bool mep_nongeneral_reg (rtx);
150 static bool mep_general_copro_reg (rtx);
151 static bool mep_nonregister (rtx);
152 static struct machine_function* mep_init_machine_status (void);
153 static rtx mep_tp_rtx (void);
154 static rtx mep_gp_rtx (void);
155 static bool mep_interrupt_p (void);
156 static bool mep_disinterrupt_p (void);
157 static bool mep_reg_set_p (rtx, rtx);
158 static bool mep_reg_set_in_function (int);
159 static bool mep_interrupt_saved_reg (int);
160 static bool mep_call_saves_register (int);
161 static rtx F (rtx);
162 static void add_constant (int, int, int, int);
163 static rtx maybe_dead_move (rtx, rtx, bool);
164 static void mep_reload_pointer (int, const char *);
165 static void mep_start_function (FILE *, HOST_WIDE_INT);
166 static bool mep_function_ok_for_sibcall (tree, tree);
167 static int unique_bit_in (HOST_WIDE_INT);
168 static int bit_size_for_clip (HOST_WIDE_INT);
169 static int bytesize (const_tree, enum machine_mode);
170 static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *);
171 static tree mep_validate_near_far (tree *, tree, tree, int, bool *);
172 static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *);
173 static tree mep_validate_interrupt (tree *, tree, tree, int, bool *);
174 static tree mep_validate_io_cb (tree *, tree, tree, int, bool *);
175 static tree mep_validate_vliw (tree *, tree, tree, int, bool *);
176 static bool mep_function_attribute_inlinable_p (const_tree);
177 static bool mep_can_inline_p (tree, tree);
178 static bool mep_lookup_pragma_disinterrupt (const char *);
179 static int mep_multiple_address_regions (tree, bool);
180 static int mep_attrlist_to_encoding (tree, tree);
181 static void mep_insert_attributes (tree, tree *);
182 static void mep_encode_section_info (tree, rtx, int);
183 static section * mep_select_section (tree, int, unsigned HOST_WIDE_INT);
184 static void mep_unique_section (tree, int);
185 static unsigned int mep_section_type_flags (tree, const char *, int);
186 static void mep_asm_named_section (const char *, unsigned int, tree);
187 static bool mep_mentioned_p (rtx, rtx, int);
188 static void mep_reorg_regmove (rtx);
189 static rtx mep_insert_repeat_label_last (rtx, rtx, bool, bool);
190 static void mep_reorg_repeat (rtx);
191 static bool mep_invertable_branch_p (rtx);
192 static void mep_invert_branch (rtx, rtx);
193 static void mep_reorg_erepeat (rtx);
194 static void mep_jmp_return_reorg (rtx);
195 static void mep_reorg_addcombine (rtx);
196 static void mep_reorg (void);
197 static void mep_init_intrinsics (void);
198 static void mep_init_builtins (void);
199 static void mep_intrinsic_unavailable (int);
200 static bool mep_get_intrinsic_insn (int, const struct cgen_insn **);
201 static bool mep_get_move_insn (int, const struct cgen_insn **);
202 static rtx mep_convert_arg (enum machine_mode, rtx);
203 static rtx mep_convert_regnum (const struct cgen_regnum_operand *, rtx);
204 static rtx mep_legitimize_arg (const struct insn_operand_data *, rtx, int);
205 static void mep_incompatible_arg (const struct insn_operand_data *, rtx, int, tree);
206 static rtx mep_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
207 static int mep_adjust_cost (rtx, rtx, rtx, int);
208 static int mep_issue_rate (void);
209 static rtx mep_find_ready_insn (rtx *, int, enum attr_slot, int);
210 static void mep_move_ready_insn (rtx *, int, rtx);
211 static int mep_sched_reorder (FILE *, int, rtx *, int *, int);
212 static rtx mep_make_bundle (rtx, rtx);
213 static void mep_bundle_insns (rtx);
214 static bool mep_rtx_cost (rtx, int, int, int, int *, bool);
215 static int mep_address_cost (rtx, enum machine_mode, addr_space_t, bool);
216 static void mep_setup_incoming_varargs (cumulative_args_t, enum machine_mode,
217 tree, int *, int);
218 static bool mep_pass_by_reference (cumulative_args_t cum, enum machine_mode,
219 const_tree, bool);
220 static rtx mep_function_arg (cumulative_args_t, enum machine_mode,
221 const_tree, bool);
222 static void mep_function_arg_advance (cumulative_args_t, enum machine_mode,
223 const_tree, bool);
224 static bool mep_vector_mode_supported_p (enum machine_mode);
225 static rtx mep_allocate_initial_value (rtx);
226 static void mep_asm_init_sections (void);
227 static int mep_comp_type_attributes (const_tree, const_tree);
228 static bool mep_narrow_volatile_bitfield (void);
229 static rtx mep_expand_builtin_saveregs (void);
230 static tree mep_build_builtin_va_list (void);
231 static void mep_expand_va_start (tree, rtx);
232 static tree mep_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
233 static bool mep_can_eliminate (const int, const int);
234 static void mep_conditional_register_usage (void);
235 static void mep_trampoline_init (rtx, tree, rtx);
236 \f
237 #define WANT_GCC_DEFINITIONS
238 #include "mep-intrin.h"
239 #undef WANT_GCC_DEFINITIONS
240
241 \f
242 /* Command Line Option Support. */
243
244 char mep_leaf_registers [FIRST_PSEUDO_REGISTER];
245
246 /* True if we can use cmov instructions to move values back and forth
247 between core and coprocessor registers. */
248 bool mep_have_core_copro_moves_p;
249
250 /* True if we can use cmov instructions (or a work-alike) to move
251 values between coprocessor registers. */
252 bool mep_have_copro_copro_moves_p;
253
254 /* A table of all coprocessor instructions that can act like
255 a coprocessor-to-coprocessor cmov. */
256 static const int mep_cmov_insns[] = {
257 mep_cmov,
258 mep_cpmov,
259 mep_fmovs,
260 mep_caddi3,
261 mep_csubi3,
262 mep_candi3,
263 mep_cori3,
264 mep_cxori3,
265 mep_cand3,
266 mep_cor3
267 };
268
269 \f
270 static void
271 mep_set_leaf_registers (int enable)
272 {
273 int i;
274
275 if (mep_leaf_registers[0] != enable)
276 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
277 mep_leaf_registers[i] = enable;
278 }
279
280 static void
281 mep_conditional_register_usage (void)
282 {
283 int i;
284
285 if (!TARGET_OPT_MULT && !TARGET_OPT_DIV)
286 {
287 fixed_regs[HI_REGNO] = 1;
288 fixed_regs[LO_REGNO] = 1;
289 call_used_regs[HI_REGNO] = 1;
290 call_used_regs[LO_REGNO] = 1;
291 }
292
293 for (i = FIRST_SHADOW_REGISTER; i <= LAST_SHADOW_REGISTER; i++)
294 global_regs[i] = 1;
295 }
296
297 static void
298 mep_option_override (void)
299 {
300 unsigned int i;
301 int j;
302 cl_deferred_option *opt;
303 vec<cl_deferred_option> *v = (vec<cl_deferred_option> *) mep_deferred_options;
304
305 if (v)
306 FOR_EACH_VEC_ELT (*v, i, opt)
307 {
308 switch (opt->opt_index)
309 {
310 case OPT_mivc2:
311 for (j = 0; j < 32; j++)
312 fixed_regs[j + 48] = 0;
313 for (j = 0; j < 32; j++)
314 call_used_regs[j + 48] = 1;
315 for (j = 6; j < 8; j++)
316 call_used_regs[j + 48] = 0;
317
318 #define RN(n,s) reg_names[FIRST_CCR_REGNO + n] = s
319 RN (0, "$csar0");
320 RN (1, "$cc");
321 RN (4, "$cofr0");
322 RN (5, "$cofr1");
323 RN (6, "$cofa0");
324 RN (7, "$cofa1");
325 RN (15, "$csar1");
326
327 RN (16, "$acc0_0");
328 RN (17, "$acc0_1");
329 RN (18, "$acc0_2");
330 RN (19, "$acc0_3");
331 RN (20, "$acc0_4");
332 RN (21, "$acc0_5");
333 RN (22, "$acc0_6");
334 RN (23, "$acc0_7");
335
336 RN (24, "$acc1_0");
337 RN (25, "$acc1_1");
338 RN (26, "$acc1_2");
339 RN (27, "$acc1_3");
340 RN (28, "$acc1_4");
341 RN (29, "$acc1_5");
342 RN (30, "$acc1_6");
343 RN (31, "$acc1_7");
344 #undef RN
345 break;
346
347 default:
348 gcc_unreachable ();
349 }
350 }
351
352 if (flag_pic == 1)
353 warning (OPT_fpic, "-fpic is not supported");
354 if (flag_pic == 2)
355 warning (OPT_fPIC, "-fPIC is not supported");
356 if (TARGET_S && TARGET_M)
357 error ("only one of -ms and -mm may be given");
358 if (TARGET_S && TARGET_L)
359 error ("only one of -ms and -ml may be given");
360 if (TARGET_M && TARGET_L)
361 error ("only one of -mm and -ml may be given");
362 if (TARGET_S && global_options_set.x_mep_tiny_cutoff)
363 error ("only one of -ms and -mtiny= may be given");
364 if (TARGET_M && global_options_set.x_mep_tiny_cutoff)
365 error ("only one of -mm and -mtiny= may be given");
366 if (TARGET_OPT_CLIP && ! TARGET_OPT_MINMAX)
367 warning (0, "-mclip currently has no effect without -mminmax");
368
369 if (mep_const_section)
370 {
371 if (strcmp (mep_const_section, "tiny") != 0
372 && strcmp (mep_const_section, "near") != 0
373 && strcmp (mep_const_section, "far") != 0)
374 error ("-mc= must be -mc=tiny, -mc=near, or -mc=far");
375 }
376
377 if (TARGET_S)
378 mep_tiny_cutoff = 65536;
379 if (TARGET_M)
380 mep_tiny_cutoff = 0;
381 if (TARGET_L && ! global_options_set.x_mep_tiny_cutoff)
382 mep_tiny_cutoff = 0;
383
384 if (TARGET_64BIT_CR_REGS)
385 flag_split_wide_types = 0;
386
387 init_machine_status = mep_init_machine_status;
388 mep_init_intrinsics ();
389 }
390
391 /* Pattern Support - constraints, predicates, expanders. */
392
393 /* MEP has very few instructions that can refer to the span of
394 addresses used by symbols, so it's common to check for them. */
395
396 static bool
397 symbol_p (rtx x)
398 {
399 int c = GET_CODE (x);
400
401 return (c == CONST_INT
402 || c == CONST
403 || c == SYMBOL_REF);
404 }
405
406 static bool
407 symbolref_p (rtx x)
408 {
409 int c;
410
411 if (GET_CODE (x) != MEM)
412 return false;
413
414 c = GET_CODE (XEXP (x, 0));
415 return (c == CONST_INT
416 || c == CONST
417 || c == SYMBOL_REF);
418 }
419
420 /* static const char *reg_class_names[] = REG_CLASS_NAMES; */
421
422 #define GEN_REG(R, STRICT) \
423 (GR_REGNO_P (R) \
424 || (!STRICT \
425 && ((R) == ARG_POINTER_REGNUM \
426 || (R) >= FIRST_PSEUDO_REGISTER)))
427
428 static char pattern[12], *patternp;
429 static GTY(()) rtx patternr[12];
430 #define RTX_IS(x) (strcmp (pattern, x) == 0)
431
432 static void
433 encode_pattern_1 (rtx x)
434 {
435 int i;
436
437 if (patternp == pattern + sizeof (pattern) - 2)
438 {
439 patternp[-1] = '?';
440 return;
441 }
442
443 patternr[patternp-pattern] = x;
444
445 switch (GET_CODE (x))
446 {
447 case REG:
448 *patternp++ = 'r';
449 break;
450 case MEM:
451 *patternp++ = 'm';
452 case CONST:
453 encode_pattern_1 (XEXP(x, 0));
454 break;
455 case PLUS:
456 *patternp++ = '+';
457 encode_pattern_1 (XEXP(x, 0));
458 encode_pattern_1 (XEXP(x, 1));
459 break;
460 case LO_SUM:
461 *patternp++ = 'L';
462 encode_pattern_1 (XEXP(x, 0));
463 encode_pattern_1 (XEXP(x, 1));
464 break;
465 case HIGH:
466 *patternp++ = 'H';
467 encode_pattern_1 (XEXP(x, 0));
468 break;
469 case SYMBOL_REF:
470 *patternp++ = 's';
471 break;
472 case LABEL_REF:
473 *patternp++ = 'l';
474 break;
475 case CONST_INT:
476 case CONST_DOUBLE:
477 *patternp++ = 'i';
478 break;
479 case UNSPEC:
480 *patternp++ = 'u';
481 *patternp++ = '0' + XCINT(x, 1, UNSPEC);
482 for (i=0; i<XVECLEN (x, 0); i++)
483 encode_pattern_1 (XVECEXP (x, 0, i));
484 break;
485 case USE:
486 *patternp++ = 'U';
487 break;
488 default:
489 *patternp++ = '?';
490 #if 0
491 fprintf (stderr, "can't encode pattern %s\n", GET_RTX_NAME(GET_CODE(x)));
492 debug_rtx (x);
493 gcc_unreachable ();
494 #endif
495 break;
496 }
497 }
498
499 static void
500 encode_pattern (rtx x)
501 {
502 patternp = pattern;
503 encode_pattern_1 (x);
504 *patternp = 0;
505 }
506
507 int
508 mep_section_tag (rtx x)
509 {
510 const char *name;
511
512 while (1)
513 {
514 switch (GET_CODE (x))
515 {
516 case MEM:
517 case CONST:
518 x = XEXP (x, 0);
519 break;
520 case UNSPEC:
521 x = XVECEXP (x, 0, 0);
522 break;
523 case PLUS:
524 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
525 return 0;
526 x = XEXP (x, 0);
527 break;
528 default:
529 goto done;
530 }
531 }
532 done:
533 if (GET_CODE (x) != SYMBOL_REF)
534 return 0;
535 name = XSTR (x, 0);
536 if (name[0] == '@' && name[2] == '.')
537 {
538 if (name[1] == 'i' || name[1] == 'I')
539 {
540 if (name[1] == 'I')
541 return 'f'; /* near */
542 return 'n'; /* far */
543 }
544 return name[1];
545 }
546 return 0;
547 }
548
549 int
550 mep_regno_reg_class (int regno)
551 {
552 switch (regno)
553 {
554 case SP_REGNO: return SP_REGS;
555 case TP_REGNO: return TP_REGS;
556 case GP_REGNO: return GP_REGS;
557 case 0: return R0_REGS;
558 case HI_REGNO: return HI_REGS;
559 case LO_REGNO: return LO_REGS;
560 case ARG_POINTER_REGNUM: return GENERAL_REGS;
561 }
562
563 if (GR_REGNO_P (regno))
564 return regno < FIRST_GR_REGNO + 8 ? TPREL_REGS : GENERAL_REGS;
565 if (CONTROL_REGNO_P (regno))
566 return CONTROL_REGS;
567
568 if (CR_REGNO_P (regno))
569 {
570 int i, j;
571
572 /* Search for the register amongst user-defined subclasses of
573 the coprocessor registers. */
574 for (i = USER0_REGS; i <= USER3_REGS; ++i)
575 {
576 if (! TEST_HARD_REG_BIT (reg_class_contents[i], regno))
577 continue;
578 for (j = 0; j < N_REG_CLASSES; ++j)
579 {
580 enum reg_class sub = reg_class_subclasses[i][j];
581
582 if (sub == LIM_REG_CLASSES)
583 return i;
584 if (TEST_HARD_REG_BIT (reg_class_contents[sub], regno))
585 break;
586 }
587 }
588
589 return LOADABLE_CR_REGNO_P (regno) ? LOADABLE_CR_REGS : CR_REGS;
590 }
591
592 if (CCR_REGNO_P (regno))
593 return CCR_REGS;
594
595 gcc_assert (regno >= FIRST_SHADOW_REGISTER && regno <= LAST_SHADOW_REGISTER);
596 return NO_REGS;
597 }
598
599 static bool
600 const_in_range (rtx x, int minv, int maxv)
601 {
602 return (GET_CODE (x) == CONST_INT
603 && INTVAL (x) >= minv
604 && INTVAL (x) <= maxv);
605 }
606
607 /* Given three integer registers DEST, SRC1 and SRC2, return an rtx X
608 such that "mulr DEST,X" will calculate DEST = SRC1 * SRC2. If a move
609 is needed, emit it before INSN if INSN is nonnull, otherwise emit it
610 at the end of the insn stream. */
611
612 rtx
613 mep_mulr_source (rtx insn, rtx dest, rtx src1, rtx src2)
614 {
615 if (rtx_equal_p (dest, src1))
616 return src2;
617 else if (rtx_equal_p (dest, src2))
618 return src1;
619 else
620 {
621 if (insn == 0)
622 emit_insn (gen_movsi (copy_rtx (dest), src1));
623 else
624 emit_insn_before (gen_movsi (copy_rtx (dest), src1), insn);
625 return src2;
626 }
627 }
628
629 /* Replace INSN's pattern with PATTERN, a multiplication PARALLEL.
630 Change the last element of PATTERN from (clobber (scratch:SI))
631 to (clobber (reg:SI HI_REGNO)). */
632
633 static void
634 mep_rewrite_mult (rtx insn, rtx pattern)
635 {
636 rtx hi_clobber;
637
638 hi_clobber = XVECEXP (pattern, 0, XVECLEN (pattern, 0) - 1);
639 XEXP (hi_clobber, 0) = gen_rtx_REG (SImode, HI_REGNO);
640 PATTERN (insn) = pattern;
641 INSN_CODE (insn) = -1;
642 }
643
644 /* Subroutine of mep_reuse_lo_p. Rewrite instruction INSN so that it
645 calculates SRC1 * SRC2 and stores the result in $lo. Also make it
646 store the result in DEST if nonnull. */
647
648 static void
649 mep_rewrite_mulsi3 (rtx insn, rtx dest, rtx src1, rtx src2)
650 {
651 rtx lo, pattern;
652
653 lo = gen_rtx_REG (SImode, LO_REGNO);
654 if (dest)
655 pattern = gen_mulsi3r (lo, dest, copy_rtx (dest),
656 mep_mulr_source (insn, dest, src1, src2));
657 else
658 pattern = gen_mulsi3_lo (lo, src1, src2);
659 mep_rewrite_mult (insn, pattern);
660 }
661
662 /* Like mep_rewrite_mulsi3, but calculate SRC1 * SRC2 + SRC3. First copy
663 SRC3 into $lo, then use either madd or maddr. The move into $lo will
664 be deleted by a peephole2 if SRC3 is already in $lo. */
665
666 static void
667 mep_rewrite_maddsi3 (rtx insn, rtx dest, rtx src1, rtx src2, rtx src3)
668 {
669 rtx lo, pattern;
670
671 lo = gen_rtx_REG (SImode, LO_REGNO);
672 emit_insn_before (gen_movsi (copy_rtx (lo), src3), insn);
673 if (dest)
674 pattern = gen_maddsi3r (lo, dest, copy_rtx (dest),
675 mep_mulr_source (insn, dest, src1, src2),
676 copy_rtx (lo));
677 else
678 pattern = gen_maddsi3_lo (lo, src1, src2, copy_rtx (lo));
679 mep_rewrite_mult (insn, pattern);
680 }
681
682 /* Return true if $lo has the same value as integer register GPR when
683 instruction INSN is reached. If necessary, rewrite the instruction
684 that sets $lo so that it uses a proper SET, not a CLOBBER. LO is an
685 rtx for (reg:SI LO_REGNO).
686
687 This function is intended to be used by the peephole2 pass. Since
688 that pass goes from the end of a basic block to the beginning, and
689 propagates liveness information on the way, there is no need to
690 update register notes here.
691
692 If GPR_DEAD_P is true on entry, and this function returns true,
693 then the caller will replace _every_ use of GPR in and after INSN
694 with LO. This means that if the instruction that sets $lo is a
695 mulr- or maddr-type instruction, we can rewrite it to use mul or
696 madd instead. In combination with the copy progagation pass,
697 this allows us to replace sequences like:
698
699 mov GPR,R1
700 mulr GPR,R2
701
702 with:
703
704 mul R1,R2
705
706 if GPR is no longer used. */
707
708 static bool
709 mep_reuse_lo_p_1 (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
710 {
711 do
712 {
713 insn = PREV_INSN (insn);
714 if (INSN_P (insn))
715 switch (recog_memoized (insn))
716 {
717 case CODE_FOR_mulsi3_1:
718 extract_insn (insn);
719 if (rtx_equal_p (recog_data.operand[0], gpr))
720 {
721 mep_rewrite_mulsi3 (insn,
722 gpr_dead_p ? NULL : recog_data.operand[0],
723 recog_data.operand[1],
724 recog_data.operand[2]);
725 return true;
726 }
727 return false;
728
729 case CODE_FOR_maddsi3:
730 extract_insn (insn);
731 if (rtx_equal_p (recog_data.operand[0], gpr))
732 {
733 mep_rewrite_maddsi3 (insn,
734 gpr_dead_p ? NULL : recog_data.operand[0],
735 recog_data.operand[1],
736 recog_data.operand[2],
737 recog_data.operand[3]);
738 return true;
739 }
740 return false;
741
742 case CODE_FOR_mulsi3r:
743 case CODE_FOR_maddsi3r:
744 extract_insn (insn);
745 return rtx_equal_p (recog_data.operand[1], gpr);
746
747 default:
748 if (reg_set_p (lo, insn)
749 || reg_set_p (gpr, insn)
750 || volatile_insn_p (PATTERN (insn)))
751 return false;
752
753 if (gpr_dead_p && reg_referenced_p (gpr, PATTERN (insn)))
754 gpr_dead_p = false;
755 break;
756 }
757 }
758 while (!NOTE_INSN_BASIC_BLOCK_P (insn));
759 return false;
760 }
761
762 /* A wrapper around mep_reuse_lo_p_1 that preserves recog_data. */
763
764 bool
765 mep_reuse_lo_p (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
766 {
767 bool result = mep_reuse_lo_p_1 (lo, gpr, insn, gpr_dead_p);
768 extract_insn (insn);
769 return result;
770 }
771
772 /* Return true if SET can be turned into a post-modify load or store
773 that adds OFFSET to GPR. In other words, return true if SET can be
774 changed into:
775
776 (parallel [SET (set GPR (plus:SI GPR OFFSET))]).
777
778 It's OK to change SET to an equivalent operation in order to
779 make it match. */
780
781 static bool
782 mep_use_post_modify_for_set_p (rtx set, rtx gpr, rtx offset)
783 {
784 rtx *reg, *mem;
785 unsigned int reg_bytes, mem_bytes;
786 enum machine_mode reg_mode, mem_mode;
787
788 /* Only simple SETs can be converted. */
789 if (GET_CODE (set) != SET)
790 return false;
791
792 /* Point REG to what we hope will be the register side of the set and
793 MEM to what we hope will be the memory side. */
794 if (GET_CODE (SET_DEST (set)) == MEM)
795 {
796 mem = &SET_DEST (set);
797 reg = &SET_SRC (set);
798 }
799 else
800 {
801 reg = &SET_DEST (set);
802 mem = &SET_SRC (set);
803 if (GET_CODE (*mem) == SIGN_EXTEND)
804 mem = &XEXP (*mem, 0);
805 }
806
807 /* Check that *REG is a suitable coprocessor register. */
808 if (GET_CODE (*reg) != REG || !LOADABLE_CR_REGNO_P (REGNO (*reg)))
809 return false;
810
811 /* Check that *MEM is a suitable memory reference. */
812 if (GET_CODE (*mem) != MEM || !rtx_equal_p (XEXP (*mem, 0), gpr))
813 return false;
814
815 /* Get the number of bytes in each operand. */
816 mem_bytes = GET_MODE_SIZE (GET_MODE (*mem));
817 reg_bytes = GET_MODE_SIZE (GET_MODE (*reg));
818
819 /* Check that OFFSET is suitably aligned. */
820 if (INTVAL (offset) & (mem_bytes - 1))
821 return false;
822
823 /* Convert *MEM to a normal integer mode. */
824 mem_mode = mode_for_size (mem_bytes * BITS_PER_UNIT, MODE_INT, 0);
825 *mem = change_address (*mem, mem_mode, NULL);
826
827 /* Adjust *REG as well. */
828 *reg = shallow_copy_rtx (*reg);
829 if (reg == &SET_DEST (set) && reg_bytes < UNITS_PER_WORD)
830 {
831 /* SET is a subword load. Convert it to an explicit extension. */
832 PUT_MODE (*reg, SImode);
833 *mem = gen_rtx_SIGN_EXTEND (SImode, *mem);
834 }
835 else
836 {
837 reg_mode = mode_for_size (reg_bytes * BITS_PER_UNIT, MODE_INT, 0);
838 PUT_MODE (*reg, reg_mode);
839 }
840 return true;
841 }
842
843 /* Return the effect of frame-related instruction INSN. */
844
845 static rtx
846 mep_frame_expr (rtx insn)
847 {
848 rtx note, expr;
849
850 note = find_reg_note (insn, REG_FRAME_RELATED_EXPR, 0);
851 expr = (note != 0 ? XEXP (note, 0) : copy_rtx (PATTERN (insn)));
852 RTX_FRAME_RELATED_P (expr) = 1;
853 return expr;
854 }
855
856 /* Merge instructions INSN1 and INSN2 using a PARALLEL. Store the
857 new pattern in INSN1; INSN2 will be deleted by the caller. */
858
859 static void
860 mep_make_parallel (rtx insn1, rtx insn2)
861 {
862 rtx expr;
863
864 if (RTX_FRAME_RELATED_P (insn2))
865 {
866 expr = mep_frame_expr (insn2);
867 if (RTX_FRAME_RELATED_P (insn1))
868 expr = gen_rtx_SEQUENCE (VOIDmode,
869 gen_rtvec (2, mep_frame_expr (insn1), expr));
870 set_unique_reg_note (insn1, REG_FRAME_RELATED_EXPR, expr);
871 RTX_FRAME_RELATED_P (insn1) = 1;
872 }
873
874 PATTERN (insn1) = gen_rtx_PARALLEL (VOIDmode,
875 gen_rtvec (2, PATTERN (insn1),
876 PATTERN (insn2)));
877 INSN_CODE (insn1) = -1;
878 }
879
880 /* SET_INSN is an instruction that adds OFFSET to REG. Go back through
881 the basic block to see if any previous load or store instruction can
882 be persuaded to do SET_INSN as a side-effect. Return true if so. */
883
884 static bool
885 mep_use_post_modify_p_1 (rtx set_insn, rtx reg, rtx offset)
886 {
887 rtx insn;
888
889 insn = set_insn;
890 do
891 {
892 insn = PREV_INSN (insn);
893 if (INSN_P (insn))
894 {
895 if (mep_use_post_modify_for_set_p (PATTERN (insn), reg, offset))
896 {
897 mep_make_parallel (insn, set_insn);
898 return true;
899 }
900
901 if (reg_set_p (reg, insn)
902 || reg_referenced_p (reg, PATTERN (insn))
903 || volatile_insn_p (PATTERN (insn)))
904 return false;
905 }
906 }
907 while (!NOTE_INSN_BASIC_BLOCK_P (insn));
908 return false;
909 }
910
911 /* A wrapper around mep_use_post_modify_p_1 that preserves recog_data. */
912
913 bool
914 mep_use_post_modify_p (rtx insn, rtx reg, rtx offset)
915 {
916 bool result = mep_use_post_modify_p_1 (insn, reg, offset);
917 extract_insn (insn);
918 return result;
919 }
920
921 bool
922 mep_allow_clip (rtx ux, rtx lx, int s)
923 {
924 HOST_WIDE_INT u = INTVAL (ux);
925 HOST_WIDE_INT l = INTVAL (lx);
926 int i;
927
928 if (!TARGET_OPT_CLIP)
929 return false;
930
931 if (s)
932 {
933 for (i = 0; i < 30; i ++)
934 if ((u == ((HOST_WIDE_INT) 1 << i) - 1)
935 && (l == - ((HOST_WIDE_INT) 1 << i)))
936 return true;
937 }
938 else
939 {
940 if (l != 0)
941 return false;
942
943 for (i = 0; i < 30; i ++)
944 if ((u == ((HOST_WIDE_INT) 1 << i) - 1))
945 return true;
946 }
947 return false;
948 }
949
950 bool
951 mep_bit_position_p (rtx x, bool looking_for)
952 {
953 if (GET_CODE (x) != CONST_INT)
954 return false;
955 switch ((int) INTVAL(x) & 0xff)
956 {
957 case 0x01: case 0x02: case 0x04: case 0x08:
958 case 0x10: case 0x20: case 0x40: case 0x80:
959 return looking_for;
960 case 0xfe: case 0xfd: case 0xfb: case 0xf7:
961 case 0xef: case 0xdf: case 0xbf: case 0x7f:
962 return !looking_for;
963 }
964 return false;
965 }
966
967 static bool
968 move_needs_splitting (rtx dest, rtx src,
969 enum machine_mode mode ATTRIBUTE_UNUSED)
970 {
971 int s = mep_section_tag (src);
972
973 while (1)
974 {
975 if (GET_CODE (src) == CONST
976 || GET_CODE (src) == MEM)
977 src = XEXP (src, 0);
978 else if (GET_CODE (src) == SYMBOL_REF
979 || GET_CODE (src) == LABEL_REF
980 || GET_CODE (src) == PLUS)
981 break;
982 else
983 return false;
984 }
985 if (s == 'f'
986 || (GET_CODE (src) == PLUS
987 && GET_CODE (XEXP (src, 1)) == CONST_INT
988 && (INTVAL (XEXP (src, 1)) < -65536
989 || INTVAL (XEXP (src, 1)) > 0xffffff))
990 || (GET_CODE (dest) == REG
991 && REGNO (dest) > 7 && REGNO (dest) < FIRST_PSEUDO_REGISTER))
992 return true;
993 return false;
994 }
995
996 bool
997 mep_split_mov (rtx *operands, int symbolic)
998 {
999 if (symbolic)
1000 {
1001 if (move_needs_splitting (operands[0], operands[1], SImode))
1002 return true;
1003 return false;
1004 }
1005
1006 if (GET_CODE (operands[1]) != CONST_INT)
1007 return false;
1008
1009 if (constraint_satisfied_p (operands[1], CONSTRAINT_I)
1010 || constraint_satisfied_p (operands[1], CONSTRAINT_J)
1011 || constraint_satisfied_p (operands[1], CONSTRAINT_O))
1012 return false;
1013
1014 if (((!reload_completed && !reload_in_progress)
1015 || (REG_P (operands[0]) && REGNO (operands[0]) < 8))
1016 && constraint_satisfied_p (operands[1], CONSTRAINT_K))
1017 return false;
1018
1019 return true;
1020 }
1021
1022 /* Irritatingly, the "jsrv" insn *toggles* PSW.OM rather than set
1023 it to one specific value. So the insn chosen depends on whether
1024 the source and destination modes match. */
1025
1026 bool
1027 mep_vliw_mode_match (rtx tgt)
1028 {
1029 bool src_vliw = mep_vliw_function_p (cfun->decl);
1030 bool tgt_vliw = INTVAL (tgt);
1031
1032 return src_vliw == tgt_vliw;
1033 }
1034
1035 /* Like the above, but also test for near/far mismatches. */
1036
1037 bool
1038 mep_vliw_jmp_match (rtx tgt)
1039 {
1040 bool src_vliw = mep_vliw_function_p (cfun->decl);
1041 bool tgt_vliw = INTVAL (tgt);
1042
1043 if (mep_section_tag (DECL_RTL (cfun->decl)) == 'f')
1044 return false;
1045
1046 return src_vliw == tgt_vliw;
1047 }
1048
1049 bool
1050 mep_multi_slot (rtx x)
1051 {
1052 return get_attr_slot (x) == SLOT_MULTI;
1053 }
1054
1055 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1056
1057 static bool
1058 mep_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1059 {
1060 /* We can't convert symbol values to gp- or tp-rel values after
1061 reload, as reload might have used $gp or $tp for other
1062 purposes. */
1063 if (GET_CODE (x) == SYMBOL_REF && (reload_in_progress || reload_completed))
1064 {
1065 char e = mep_section_tag (x);
1066 return (e != 't' && e != 'b');
1067 }
1068 return 1;
1069 }
1070
1071 /* Be careful not to use macros that need to be compiled one way for
1072 strict, and another way for not-strict, like REG_OK_FOR_BASE_P. */
1073
1074 bool
1075 mep_legitimate_address (enum machine_mode mode, rtx x, int strict)
1076 {
1077 int the_tag;
1078
1079 #define DEBUG_LEGIT 0
1080 #if DEBUG_LEGIT
1081 fprintf (stderr, "legit: mode %s strict %d ", mode_name[mode], strict);
1082 debug_rtx (x);
1083 #endif
1084
1085 if (GET_CODE (x) == LO_SUM
1086 && GET_CODE (XEXP (x, 0)) == REG
1087 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1088 && CONSTANT_P (XEXP (x, 1)))
1089 {
1090 if (GET_MODE_SIZE (mode) > 4)
1091 {
1092 /* We will end up splitting this, and lo_sums are not
1093 offsettable for us. */
1094 #if DEBUG_LEGIT
1095 fprintf(stderr, " - nope, %%lo(sym)[reg] not splittable\n");
1096 #endif
1097 return false;
1098 }
1099 #if DEBUG_LEGIT
1100 fprintf (stderr, " - yup, %%lo(sym)[reg]\n");
1101 #endif
1102 return true;
1103 }
1104
1105 if (GET_CODE (x) == REG
1106 && GEN_REG (REGNO (x), strict))
1107 {
1108 #if DEBUG_LEGIT
1109 fprintf (stderr, " - yup, [reg]\n");
1110 #endif
1111 return true;
1112 }
1113
1114 if (GET_CODE (x) == PLUS
1115 && GET_CODE (XEXP (x, 0)) == REG
1116 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1117 && const_in_range (XEXP (x, 1), -32768, 32767))
1118 {
1119 #if DEBUG_LEGIT
1120 fprintf (stderr, " - yup, [reg+const]\n");
1121 #endif
1122 return true;
1123 }
1124
1125 if (GET_CODE (x) == PLUS
1126 && GET_CODE (XEXP (x, 0)) == REG
1127 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1128 && GET_CODE (XEXP (x, 1)) == CONST
1129 && (GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
1130 || (GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
1131 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == UNSPEC
1132 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)))
1133 {
1134 #if DEBUG_LEGIT
1135 fprintf (stderr, " - yup, [reg+unspec]\n");
1136 #endif
1137 return true;
1138 }
1139
1140 the_tag = mep_section_tag (x);
1141
1142 if (the_tag == 'f')
1143 {
1144 #if DEBUG_LEGIT
1145 fprintf (stderr, " - nope, [far]\n");
1146 #endif
1147 return false;
1148 }
1149
1150 if (mode == VOIDmode
1151 && GET_CODE (x) == SYMBOL_REF)
1152 {
1153 #if DEBUG_LEGIT
1154 fprintf (stderr, " - yup, call [symbol]\n");
1155 #endif
1156 return true;
1157 }
1158
1159 if ((mode == SImode || mode == SFmode)
1160 && CONSTANT_P (x)
1161 && mep_legitimate_constant_p (mode, x)
1162 && the_tag != 't' && the_tag != 'b')
1163 {
1164 if (GET_CODE (x) != CONST_INT
1165 || (INTVAL (x) <= 0xfffff
1166 && INTVAL (x) >= 0
1167 && (INTVAL (x) % 4) == 0))
1168 {
1169 #if DEBUG_LEGIT
1170 fprintf (stderr, " - yup, [const]\n");
1171 #endif
1172 return true;
1173 }
1174 }
1175
1176 #if DEBUG_LEGIT
1177 fprintf (stderr, " - nope.\n");
1178 #endif
1179 return false;
1180 }
1181
1182 int
1183 mep_legitimize_reload_address (rtx *x, enum machine_mode mode, int opnum,
1184 int type_i,
1185 int ind_levels ATTRIBUTE_UNUSED)
1186 {
1187 enum reload_type type = (enum reload_type) type_i;
1188
1189 if (GET_CODE (*x) == PLUS
1190 && GET_CODE (XEXP (*x, 0)) == MEM
1191 && GET_CODE (XEXP (*x, 1)) == REG)
1192 {
1193 /* GCC will by default copy the MEM into a REG, which results in
1194 an invalid address. For us, the best thing to do is move the
1195 whole expression to a REG. */
1196 push_reload (*x, NULL_RTX, x, NULL,
1197 GENERAL_REGS, mode, VOIDmode,
1198 0, 0, opnum, type);
1199 return 1;
1200 }
1201
1202 if (GET_CODE (*x) == PLUS
1203 && GET_CODE (XEXP (*x, 0)) == SYMBOL_REF
1204 && GET_CODE (XEXP (*x, 1)) == CONST_INT)
1205 {
1206 char e = mep_section_tag (XEXP (*x, 0));
1207
1208 if (e != 't' && e != 'b')
1209 {
1210 /* GCC thinks that (sym+const) is a valid address. Well,
1211 sometimes it is, this time it isn't. The best thing to
1212 do is reload the symbol to a register, since reg+int
1213 tends to work, and we can't just add the symbol and
1214 constant anyway. */
1215 push_reload (XEXP (*x, 0), NULL_RTX, &(XEXP(*x, 0)), NULL,
1216 GENERAL_REGS, mode, VOIDmode,
1217 0, 0, opnum, type);
1218 return 1;
1219 }
1220 }
1221 return 0;
1222 }
1223
1224 int
1225 mep_core_address_length (rtx insn, int opn)
1226 {
1227 rtx set = single_set (insn);
1228 rtx mem = XEXP (set, opn);
1229 rtx other = XEXP (set, 1-opn);
1230 rtx addr = XEXP (mem, 0);
1231
1232 if (register_operand (addr, Pmode))
1233 return 2;
1234 if (GET_CODE (addr) == PLUS)
1235 {
1236 rtx addend = XEXP (addr, 1);
1237
1238 gcc_assert (REG_P (XEXP (addr, 0)));
1239
1240 switch (REGNO (XEXP (addr, 0)))
1241 {
1242 case STACK_POINTER_REGNUM:
1243 if (GET_MODE_SIZE (GET_MODE (mem)) == 4
1244 && mep_imm7a4_operand (addend, VOIDmode))
1245 return 2;
1246 break;
1247
1248 case 13: /* TP */
1249 gcc_assert (REG_P (other));
1250
1251 if (REGNO (other) >= 8)
1252 break;
1253
1254 if (GET_CODE (addend) == CONST
1255 && GET_CODE (XEXP (addend, 0)) == UNSPEC
1256 && XINT (XEXP (addend, 0), 1) == UNS_TPREL)
1257 return 2;
1258
1259 if (GET_CODE (addend) == CONST_INT
1260 && INTVAL (addend) >= 0
1261 && INTVAL (addend) <= 127
1262 && INTVAL (addend) % GET_MODE_SIZE (GET_MODE (mem)) == 0)
1263 return 2;
1264 break;
1265 }
1266 }
1267
1268 return 4;
1269 }
1270
1271 int
1272 mep_cop_address_length (rtx insn, int opn)
1273 {
1274 rtx set = single_set (insn);
1275 rtx mem = XEXP (set, opn);
1276 rtx addr = XEXP (mem, 0);
1277
1278 if (GET_CODE (mem) != MEM)
1279 return 2;
1280 if (register_operand (addr, Pmode))
1281 return 2;
1282 if (GET_CODE (addr) == POST_INC)
1283 return 2;
1284
1285 return 4;
1286 }
1287
1288 #define DEBUG_EXPAND_MOV 0
1289 bool
1290 mep_expand_mov (rtx *operands, enum machine_mode mode)
1291 {
1292 int i, t;
1293 int tag[2];
1294 rtx tpsym, tpoffs;
1295 int post_reload = 0;
1296
1297 tag[0] = mep_section_tag (operands[0]);
1298 tag[1] = mep_section_tag (operands[1]);
1299
1300 if (!reload_in_progress
1301 && !reload_completed
1302 && GET_CODE (operands[0]) != REG
1303 && GET_CODE (operands[0]) != SUBREG
1304 && GET_CODE (operands[1]) != REG
1305 && GET_CODE (operands[1]) != SUBREG)
1306 operands[1] = copy_to_mode_reg (mode, operands[1]);
1307
1308 #if DEBUG_EXPAND_MOV
1309 fprintf(stderr, "expand move %s %d\n", mode_name[mode],
1310 reload_in_progress || reload_completed);
1311 debug_rtx (operands[0]);
1312 debug_rtx (operands[1]);
1313 #endif
1314
1315 if (mode == DImode || mode == DFmode)
1316 return false;
1317
1318 if (reload_in_progress || reload_completed)
1319 {
1320 rtx r;
1321
1322 if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == TP_REGNO)
1323 cfun->machine->reload_changes_tp = true;
1324
1325 if (tag[0] == 't' || tag[1] == 't')
1326 {
1327 r = has_hard_reg_initial_val (Pmode, GP_REGNO);
1328 if (!r || GET_CODE (r) != REG || REGNO (r) != GP_REGNO)
1329 post_reload = 1;
1330 }
1331 if (tag[0] == 'b' || tag[1] == 'b')
1332 {
1333 r = has_hard_reg_initial_val (Pmode, TP_REGNO);
1334 if (!r || GET_CODE (r) != REG || REGNO (r) != TP_REGNO)
1335 post_reload = 1;
1336 }
1337 if (cfun->machine->reload_changes_tp == true)
1338 post_reload = 1;
1339 }
1340
1341 if (!post_reload)
1342 {
1343 rtx n;
1344 if (symbol_p (operands[1]))
1345 {
1346 t = mep_section_tag (operands[1]);
1347 if (t == 'b' || t == 't')
1348 {
1349
1350 if (GET_CODE (operands[1]) == SYMBOL_REF)
1351 {
1352 tpsym = operands[1];
1353 n = gen_rtx_UNSPEC (mode,
1354 gen_rtvec (1, operands[1]),
1355 t == 'b' ? UNS_TPREL : UNS_GPREL);
1356 n = gen_rtx_CONST (mode, n);
1357 }
1358 else if (GET_CODE (operands[1]) == CONST
1359 && GET_CODE (XEXP (operands[1], 0)) == PLUS
1360 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
1361 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
1362 {
1363 tpsym = XEXP (XEXP (operands[1], 0), 0);
1364 tpoffs = XEXP (XEXP (operands[1], 0), 1);
1365 n = gen_rtx_UNSPEC (mode,
1366 gen_rtvec (1, tpsym),
1367 t == 'b' ? UNS_TPREL : UNS_GPREL);
1368 n = gen_rtx_PLUS (mode, n, tpoffs);
1369 n = gen_rtx_CONST (mode, n);
1370 }
1371 else if (GET_CODE (operands[1]) == CONST
1372 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
1373 return false;
1374 else
1375 {
1376 error ("unusual TP-relative address");
1377 return false;
1378 }
1379
1380 n = gen_rtx_PLUS (mode, (t == 'b' ? mep_tp_rtx ()
1381 : mep_gp_rtx ()), n);
1382 n = emit_insn (gen_rtx_SET (mode, operands[0], n));
1383 #if DEBUG_EXPAND_MOV
1384 fprintf(stderr, "mep_expand_mov emitting ");
1385 debug_rtx(n);
1386 #endif
1387 return true;
1388 }
1389 }
1390
1391 for (i=0; i < 2; i++)
1392 {
1393 t = mep_section_tag (operands[i]);
1394 if (GET_CODE (operands[i]) == MEM && (t == 'b' || t == 't'))
1395 {
1396 rtx sym, n, r;
1397 int u;
1398
1399 sym = XEXP (operands[i], 0);
1400 if (GET_CODE (sym) == CONST
1401 && GET_CODE (XEXP (sym, 0)) == UNSPEC)
1402 sym = XVECEXP (XEXP (sym, 0), 0, 0);
1403
1404 if (t == 'b')
1405 {
1406 r = mep_tp_rtx ();
1407 u = UNS_TPREL;
1408 }
1409 else
1410 {
1411 r = mep_gp_rtx ();
1412 u = UNS_GPREL;
1413 }
1414
1415 n = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), u);
1416 n = gen_rtx_CONST (Pmode, n);
1417 n = gen_rtx_PLUS (Pmode, r, n);
1418 operands[i] = replace_equiv_address (operands[i], n);
1419 }
1420 }
1421 }
1422
1423 if ((GET_CODE (operands[1]) != REG
1424 && MEP_CONTROL_REG (operands[0]))
1425 || (GET_CODE (operands[0]) != REG
1426 && MEP_CONTROL_REG (operands[1])))
1427 {
1428 rtx temp;
1429 #if DEBUG_EXPAND_MOV
1430 fprintf (stderr, "cr-mem, forcing op1 to reg\n");
1431 #endif
1432 temp = gen_reg_rtx (mode);
1433 emit_move_insn (temp, operands[1]);
1434 operands[1] = temp;
1435 }
1436
1437 if (symbolref_p (operands[0])
1438 && (mep_section_tag (XEXP (operands[0], 0)) == 'f'
1439 || (GET_MODE_SIZE (mode) != 4)))
1440 {
1441 rtx temp;
1442
1443 gcc_assert (!reload_in_progress && !reload_completed);
1444
1445 temp = force_reg (Pmode, XEXP (operands[0], 0));
1446 operands[0] = replace_equiv_address (operands[0], temp);
1447 emit_move_insn (operands[0], operands[1]);
1448 return true;
1449 }
1450
1451 if (!post_reload && (tag[1] == 't' || tag[1] == 'b'))
1452 tag[1] = 0;
1453
1454 if (symbol_p (operands[1])
1455 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1456 {
1457 emit_insn (gen_movsi_topsym_s (operands[0], operands[1]));
1458 emit_insn (gen_movsi_botsym_s (operands[0], operands[0], operands[1]));
1459 return true;
1460 }
1461
1462 if (symbolref_p (operands[1])
1463 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1464 {
1465 rtx temp;
1466
1467 if (reload_in_progress || reload_completed)
1468 temp = operands[0];
1469 else
1470 temp = gen_reg_rtx (Pmode);
1471
1472 emit_insn (gen_movsi_topsym_s (temp, operands[1]));
1473 emit_insn (gen_movsi_botsym_s (temp, temp, operands[1]));
1474 emit_move_insn (operands[0], replace_equiv_address (operands[1], temp));
1475 return true;
1476 }
1477
1478 return false;
1479 }
1480
1481 /* Cases where the pattern can't be made to use at all. */
1482
1483 bool
1484 mep_mov_ok (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1485 {
1486 int i;
1487
1488 #define DEBUG_MOV_OK 0
1489 #if DEBUG_MOV_OK
1490 fprintf (stderr, "mep_mov_ok %s %c=%c\n", mode_name[mode], mep_section_tag (operands[0]),
1491 mep_section_tag (operands[1]));
1492 debug_rtx (operands[0]);
1493 debug_rtx (operands[1]);
1494 #endif
1495
1496 /* We want the movh patterns to get these. */
1497 if (GET_CODE (operands[1]) == HIGH)
1498 return false;
1499
1500 /* We can't store a register to a far variable without using a
1501 scratch register to hold the address. Using far variables should
1502 be split by mep_emit_mov anyway. */
1503 if (mep_section_tag (operands[0]) == 'f'
1504 || mep_section_tag (operands[1]) == 'f')
1505 {
1506 #if DEBUG_MOV_OK
1507 fprintf (stderr, " - no, f\n");
1508 #endif
1509 return false;
1510 }
1511 i = mep_section_tag (operands[1]);
1512 if ((i == 'b' || i == 't') && !reload_completed && !reload_in_progress)
1513 /* These are supposed to be generated with adds of the appropriate
1514 register. During and after reload, however, we allow them to
1515 be accessed as normal symbols because adding a dependency on
1516 the base register now might cause problems. */
1517 {
1518 #if DEBUG_MOV_OK
1519 fprintf (stderr, " - no, bt\n");
1520 #endif
1521 return false;
1522 }
1523
1524 /* The only moves we can allow involve at least one general
1525 register, so require it. */
1526 for (i = 0; i < 2; i ++)
1527 {
1528 /* Allow subregs too, before reload. */
1529 rtx x = operands[i];
1530
1531 if (GET_CODE (x) == SUBREG)
1532 x = XEXP (x, 0);
1533 if (GET_CODE (x) == REG
1534 && ! MEP_CONTROL_REG (x))
1535 {
1536 #if DEBUG_MOV_OK
1537 fprintf (stderr, " - ok\n");
1538 #endif
1539 return true;
1540 }
1541 }
1542 #if DEBUG_MOV_OK
1543 fprintf (stderr, " - no, no gen reg\n");
1544 #endif
1545 return false;
1546 }
1547
1548 #define DEBUG_SPLIT_WIDE_MOVE 0
1549 void
1550 mep_split_wide_move (rtx *operands, enum machine_mode mode)
1551 {
1552 int i;
1553
1554 #if DEBUG_SPLIT_WIDE_MOVE
1555 fprintf (stderr, "\n\033[34mmep_split_wide_move\033[0m mode %s\n", mode_name[mode]);
1556 debug_rtx (operands[0]);
1557 debug_rtx (operands[1]);
1558 #endif
1559
1560 for (i = 0; i <= 1; i++)
1561 {
1562 rtx op = operands[i], hi, lo;
1563
1564 switch (GET_CODE (op))
1565 {
1566 case REG:
1567 {
1568 unsigned int regno = REGNO (op);
1569
1570 if (TARGET_64BIT_CR_REGS && CR_REGNO_P (regno))
1571 {
1572 rtx i32;
1573
1574 lo = gen_rtx_REG (SImode, regno);
1575 i32 = GEN_INT (32);
1576 hi = gen_rtx_ZERO_EXTRACT (SImode,
1577 gen_rtx_REG (DImode, regno),
1578 i32, i32);
1579 }
1580 else
1581 {
1582 hi = gen_rtx_REG (SImode, regno + TARGET_LITTLE_ENDIAN);
1583 lo = gen_rtx_REG (SImode, regno + TARGET_BIG_ENDIAN);
1584 }
1585 }
1586 break;
1587
1588 case CONST_INT:
1589 case CONST_DOUBLE:
1590 case MEM:
1591 hi = operand_subword (op, TARGET_LITTLE_ENDIAN, 0, mode);
1592 lo = operand_subword (op, TARGET_BIG_ENDIAN, 0, mode);
1593 break;
1594
1595 default:
1596 gcc_unreachable ();
1597 }
1598
1599 /* The high part of CR <- GPR moves must be done after the low part. */
1600 operands [i + 4] = lo;
1601 operands [i + 2] = hi;
1602 }
1603
1604 if (reg_mentioned_p (operands[2], operands[5])
1605 || GET_CODE (operands[2]) == ZERO_EXTRACT
1606 || GET_CODE (operands[4]) == ZERO_EXTRACT)
1607 {
1608 rtx tmp;
1609
1610 /* Overlapping register pairs -- make sure we don't
1611 early-clobber ourselves. */
1612 tmp = operands[2];
1613 operands[2] = operands[4];
1614 operands[4] = tmp;
1615 tmp = operands[3];
1616 operands[3] = operands[5];
1617 operands[5] = tmp;
1618 }
1619
1620 #if DEBUG_SPLIT_WIDE_MOVE
1621 fprintf(stderr, "\033[34m");
1622 debug_rtx (operands[2]);
1623 debug_rtx (operands[3]);
1624 debug_rtx (operands[4]);
1625 debug_rtx (operands[5]);
1626 fprintf(stderr, "\033[0m");
1627 #endif
1628 }
1629
1630 /* Emit a setcc instruction in its entirity. */
1631
1632 static bool
1633 mep_expand_setcc_1 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
1634 {
1635 rtx tmp;
1636
1637 switch (code)
1638 {
1639 case GT:
1640 case GTU:
1641 tmp = op1, op1 = op2, op2 = tmp;
1642 code = swap_condition (code);
1643 /* FALLTHRU */
1644
1645 case LT:
1646 case LTU:
1647 op1 = force_reg (SImode, op1);
1648 emit_insn (gen_rtx_SET (VOIDmode, dest,
1649 gen_rtx_fmt_ee (code, SImode, op1, op2)));
1650 return true;
1651
1652 case EQ:
1653 if (op2 != const0_rtx)
1654 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1655 mep_expand_setcc_1 (LTU, dest, op1, const1_rtx);
1656 return true;
1657
1658 case NE:
1659 /* Branchful sequence:
1660 mov dest, 0 16-bit
1661 beq op1, op2, Lover 16-bit (op2 < 16), 32-bit otherwise
1662 mov dest, 1 16-bit
1663
1664 Branchless sequence:
1665 add3 tmp, op1, -op2 32-bit (or mov + sub)
1666 sltu3 tmp, tmp, 1 16-bit
1667 xor3 dest, tmp, 1 32-bit
1668 */
1669 if (optimize_size && op2 != const0_rtx)
1670 return false;
1671
1672 if (op2 != const0_rtx)
1673 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1674
1675 op2 = gen_reg_rtx (SImode);
1676 mep_expand_setcc_1 (LTU, op2, op1, const1_rtx);
1677
1678 emit_insn (gen_rtx_SET (VOIDmode, dest,
1679 gen_rtx_XOR (SImode, op2, const1_rtx)));
1680 return true;
1681
1682 case LE:
1683 if (GET_CODE (op2) != CONST_INT
1684 || INTVAL (op2) == 0x7ffffff)
1685 return false;
1686 op2 = GEN_INT (INTVAL (op2) + 1);
1687 return mep_expand_setcc_1 (LT, dest, op1, op2);
1688
1689 case LEU:
1690 if (GET_CODE (op2) != CONST_INT
1691 || INTVAL (op2) == -1)
1692 return false;
1693 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) + 1, SImode));
1694 return mep_expand_setcc_1 (LTU, dest, op1, op2);
1695
1696 case GE:
1697 if (GET_CODE (op2) != CONST_INT
1698 || INTVAL (op2) == trunc_int_for_mode (0x80000000, SImode))
1699 return false;
1700 op2 = GEN_INT (INTVAL (op2) - 1);
1701 return mep_expand_setcc_1 (GT, dest, op1, op2);
1702
1703 case GEU:
1704 if (GET_CODE (op2) != CONST_INT
1705 || op2 == const0_rtx)
1706 return false;
1707 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) - 1, SImode));
1708 return mep_expand_setcc_1 (GTU, dest, op1, op2);
1709
1710 default:
1711 gcc_unreachable ();
1712 }
1713 }
1714
1715 bool
1716 mep_expand_setcc (rtx *operands)
1717 {
1718 rtx dest = operands[0];
1719 enum rtx_code code = GET_CODE (operands[1]);
1720 rtx op0 = operands[2];
1721 rtx op1 = operands[3];
1722
1723 return mep_expand_setcc_1 (code, dest, op0, op1);
1724 }
1725
1726 rtx
1727 mep_expand_cbranch (rtx *operands)
1728 {
1729 enum rtx_code code = GET_CODE (operands[0]);
1730 rtx op0 = operands[1];
1731 rtx op1 = operands[2];
1732 rtx tmp;
1733
1734 restart:
1735 switch (code)
1736 {
1737 case LT:
1738 if (mep_imm4_operand (op1, SImode))
1739 break;
1740
1741 tmp = gen_reg_rtx (SImode);
1742 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1743 code = NE;
1744 op0 = tmp;
1745 op1 = const0_rtx;
1746 break;
1747
1748 case GE:
1749 if (mep_imm4_operand (op1, SImode))
1750 break;
1751
1752 tmp = gen_reg_rtx (SImode);
1753 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1754
1755 code = EQ;
1756 op0 = tmp;
1757 op1 = const0_rtx;
1758 break;
1759
1760 case EQ:
1761 case NE:
1762 if (! mep_reg_or_imm4_operand (op1, SImode))
1763 op1 = force_reg (SImode, op1);
1764 break;
1765
1766 case LE:
1767 case GT:
1768 if (GET_CODE (op1) == CONST_INT
1769 && INTVAL (op1) != 0x7fffffff)
1770 {
1771 op1 = GEN_INT (INTVAL (op1) + 1);
1772 code = (code == LE ? LT : GE);
1773 goto restart;
1774 }
1775
1776 tmp = gen_reg_rtx (SImode);
1777 gcc_assert (mep_expand_setcc_1 (LT, tmp, op1, op0));
1778
1779 code = (code == LE ? EQ : NE);
1780 op0 = tmp;
1781 op1 = const0_rtx;
1782 break;
1783
1784 case LTU:
1785 if (op1 == const1_rtx)
1786 {
1787 code = EQ;
1788 op1 = const0_rtx;
1789 break;
1790 }
1791
1792 tmp = gen_reg_rtx (SImode);
1793 gcc_assert (mep_expand_setcc_1 (LTU, tmp, op0, op1));
1794 code = NE;
1795 op0 = tmp;
1796 op1 = const0_rtx;
1797 break;
1798
1799 case LEU:
1800 tmp = gen_reg_rtx (SImode);
1801 if (mep_expand_setcc_1 (LEU, tmp, op0, op1))
1802 code = NE;
1803 else if (mep_expand_setcc_1 (LTU, tmp, op1, op0))
1804 code = EQ;
1805 else
1806 gcc_unreachable ();
1807 op0 = tmp;
1808 op1 = const0_rtx;
1809 break;
1810
1811 case GTU:
1812 tmp = gen_reg_rtx (SImode);
1813 gcc_assert (mep_expand_setcc_1 (GTU, tmp, op0, op1)
1814 || mep_expand_setcc_1 (LTU, tmp, op1, op0));
1815 code = NE;
1816 op0 = tmp;
1817 op1 = const0_rtx;
1818 break;
1819
1820 case GEU:
1821 tmp = gen_reg_rtx (SImode);
1822 if (mep_expand_setcc_1 (GEU, tmp, op0, op1))
1823 code = NE;
1824 else if (mep_expand_setcc_1 (LTU, tmp, op0, op1))
1825 code = EQ;
1826 else
1827 gcc_unreachable ();
1828 op0 = tmp;
1829 op1 = const0_rtx;
1830 break;
1831
1832 default:
1833 gcc_unreachable ();
1834 }
1835
1836 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1837 }
1838
1839 const char *
1840 mep_emit_cbranch (rtx *operands, int ne)
1841 {
1842 if (GET_CODE (operands[1]) == REG)
1843 return ne ? "bne\t%0, %1, %l2" : "beq\t%0, %1, %l2";
1844 else if (INTVAL (operands[1]) == 0 && !mep_vliw_function_p(cfun->decl))
1845 return ne ? "bnez\t%0, %l2" : "beqz\t%0, %l2";
1846 else
1847 return ne ? "bnei\t%0, %1, %l2" : "beqi\t%0, %1, %l2";
1848 }
1849
1850 void
1851 mep_expand_call (rtx *operands, int returns_value)
1852 {
1853 rtx addr = operands[returns_value];
1854 rtx tp = mep_tp_rtx ();
1855 rtx gp = mep_gp_rtx ();
1856
1857 gcc_assert (GET_CODE (addr) == MEM);
1858
1859 addr = XEXP (addr, 0);
1860
1861 if (! mep_call_address_operand (addr, VOIDmode))
1862 addr = force_reg (SImode, addr);
1863
1864 if (! operands[returns_value+2])
1865 operands[returns_value+2] = const0_rtx;
1866
1867 if (returns_value)
1868 emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
1869 operands[3], tp, gp));
1870 else
1871 emit_call_insn (gen_call_internal (addr, operands[1],
1872 operands[2], tp, gp));
1873 }
1874 \f
1875 /* Aliasing Support. */
1876
1877 /* If X is a machine specific address (i.e. a symbol or label being
1878 referenced as a displacement from the GOT implemented using an
1879 UNSPEC), then return the base term. Otherwise return X. */
1880
1881 rtx
1882 mep_find_base_term (rtx x)
1883 {
1884 rtx base, term;
1885 int unspec;
1886
1887 if (GET_CODE (x) != PLUS)
1888 return x;
1889 base = XEXP (x, 0);
1890 term = XEXP (x, 1);
1891
1892 if (has_hard_reg_initial_val(Pmode, TP_REGNO)
1893 && base == mep_tp_rtx ())
1894 unspec = UNS_TPREL;
1895 else if (has_hard_reg_initial_val(Pmode, GP_REGNO)
1896 && base == mep_gp_rtx ())
1897 unspec = UNS_GPREL;
1898 else
1899 return x;
1900
1901 if (GET_CODE (term) != CONST)
1902 return x;
1903 term = XEXP (term, 0);
1904
1905 if (GET_CODE (term) != UNSPEC
1906 || XINT (term, 1) != unspec)
1907 return x;
1908
1909 return XVECEXP (term, 0, 0);
1910 }
1911 \f
1912 /* Reload Support. */
1913
1914 /* Return true if the registers in CLASS cannot represent the change from
1915 modes FROM to TO. */
1916
1917 bool
1918 mep_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
1919 enum reg_class regclass)
1920 {
1921 if (from == to)
1922 return false;
1923
1924 /* 64-bit COP regs must remain 64-bit COP regs. */
1925 if (TARGET_64BIT_CR_REGS
1926 && (regclass == CR_REGS
1927 || regclass == LOADABLE_CR_REGS)
1928 && (GET_MODE_SIZE (to) < 8
1929 || GET_MODE_SIZE (from) < 8))
1930 return true;
1931
1932 return false;
1933 }
1934
1935 #define MEP_NONGENERAL_CLASS(C) (!reg_class_subset_p (C, GENERAL_REGS))
1936
1937 static bool
1938 mep_general_reg (rtx x)
1939 {
1940 while (GET_CODE (x) == SUBREG)
1941 x = XEXP (x, 0);
1942 return GET_CODE (x) == REG && GR_REGNO_P (REGNO (x));
1943 }
1944
1945 static bool
1946 mep_nongeneral_reg (rtx x)
1947 {
1948 while (GET_CODE (x) == SUBREG)
1949 x = XEXP (x, 0);
1950 return (GET_CODE (x) == REG
1951 && !GR_REGNO_P (REGNO (x)) && REGNO (x) < FIRST_PSEUDO_REGISTER);
1952 }
1953
1954 static bool
1955 mep_general_copro_reg (rtx x)
1956 {
1957 while (GET_CODE (x) == SUBREG)
1958 x = XEXP (x, 0);
1959 return (GET_CODE (x) == REG && CR_REGNO_P (REGNO (x)));
1960 }
1961
1962 static bool
1963 mep_nonregister (rtx x)
1964 {
1965 while (GET_CODE (x) == SUBREG)
1966 x = XEXP (x, 0);
1967 return (GET_CODE (x) != REG || REGNO (x) >= FIRST_PSEUDO_REGISTER);
1968 }
1969
1970 #define DEBUG_RELOAD 0
1971
1972 /* Return the secondary reload class needed for moving value X to or
1973 from a register in coprocessor register class CLASS. */
1974
1975 static enum reg_class
1976 mep_secondary_copro_reload_class (enum reg_class rclass, rtx x)
1977 {
1978 if (mep_general_reg (x))
1979 /* We can do the move directly if mep_have_core_copro_moves_p,
1980 otherwise we need to go through memory. Either way, no secondary
1981 register is needed. */
1982 return NO_REGS;
1983
1984 if (mep_general_copro_reg (x))
1985 {
1986 /* We can do the move directly if mep_have_copro_copro_moves_p. */
1987 if (mep_have_copro_copro_moves_p)
1988 return NO_REGS;
1989
1990 /* Otherwise we can use a temporary if mep_have_core_copro_moves_p. */
1991 if (mep_have_core_copro_moves_p)
1992 return GENERAL_REGS;
1993
1994 /* Otherwise we need to do it through memory. No secondary
1995 register is needed. */
1996 return NO_REGS;
1997 }
1998
1999 if (reg_class_subset_p (rclass, LOADABLE_CR_REGS)
2000 && constraint_satisfied_p (x, CONSTRAINT_U))
2001 /* X is a memory value that we can access directly. */
2002 return NO_REGS;
2003
2004 /* We have to move X into a GPR first and then copy it to
2005 the coprocessor register. The move from the GPR to the
2006 coprocessor might be done directly or through memory,
2007 depending on mep_have_core_copro_moves_p. */
2008 return GENERAL_REGS;
2009 }
2010
2011 /* Copying X to register in RCLASS. */
2012
2013 enum reg_class
2014 mep_secondary_input_reload_class (enum reg_class rclass,
2015 enum machine_mode mode ATTRIBUTE_UNUSED,
2016 rtx x)
2017 {
2018 int rv = NO_REGS;
2019
2020 #if DEBUG_RELOAD
2021 fprintf (stderr, "secondary input reload copy to %s %s from ", reg_class_names[rclass], mode_name[mode]);
2022 debug_rtx (x);
2023 #endif
2024
2025 if (reg_class_subset_p (rclass, CR_REGS))
2026 rv = mep_secondary_copro_reload_class (rclass, x);
2027 else if (MEP_NONGENERAL_CLASS (rclass)
2028 && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2029 rv = GENERAL_REGS;
2030
2031 #if DEBUG_RELOAD
2032 fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2033 #endif
2034 return (enum reg_class) rv;
2035 }
2036
2037 /* Copying register in RCLASS to X. */
2038
2039 enum reg_class
2040 mep_secondary_output_reload_class (enum reg_class rclass,
2041 enum machine_mode mode ATTRIBUTE_UNUSED,
2042 rtx x)
2043 {
2044 int rv = NO_REGS;
2045
2046 #if DEBUG_RELOAD
2047 fprintf (stderr, "secondary output reload copy from %s %s to ", reg_class_names[rclass], mode_name[mode]);
2048 debug_rtx (x);
2049 #endif
2050
2051 if (reg_class_subset_p (rclass, CR_REGS))
2052 rv = mep_secondary_copro_reload_class (rclass, x);
2053 else if (MEP_NONGENERAL_CLASS (rclass)
2054 && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2055 rv = GENERAL_REGS;
2056
2057 #if DEBUG_RELOAD
2058 fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2059 #endif
2060
2061 return (enum reg_class) rv;
2062 }
2063
2064 /* Implement SECONDARY_MEMORY_NEEDED. */
2065
2066 bool
2067 mep_secondary_memory_needed (enum reg_class rclass1, enum reg_class rclass2,
2068 enum machine_mode mode ATTRIBUTE_UNUSED)
2069 {
2070 if (!mep_have_core_copro_moves_p)
2071 {
2072 if (reg_classes_intersect_p (rclass1, CR_REGS)
2073 && reg_classes_intersect_p (rclass2, GENERAL_REGS))
2074 return true;
2075 if (reg_classes_intersect_p (rclass2, CR_REGS)
2076 && reg_classes_intersect_p (rclass1, GENERAL_REGS))
2077 return true;
2078 if (!mep_have_copro_copro_moves_p
2079 && reg_classes_intersect_p (rclass1, CR_REGS)
2080 && reg_classes_intersect_p (rclass2, CR_REGS))
2081 return true;
2082 }
2083 return false;
2084 }
2085
2086 void
2087 mep_expand_reload (rtx *operands, enum machine_mode mode)
2088 {
2089 /* There are three cases for each direction:
2090 register, farsym
2091 control, farsym
2092 control, nearsym */
2093
2094 int s0 = mep_section_tag (operands[0]) == 'f';
2095 int s1 = mep_section_tag (operands[1]) == 'f';
2096 int c0 = mep_nongeneral_reg (operands[0]);
2097 int c1 = mep_nongeneral_reg (operands[1]);
2098 int which = (s0 ? 20:0) + (c0 ? 10:0) + (s1 ? 2:0) + (c1 ? 1:0);
2099
2100 #if DEBUG_RELOAD
2101 fprintf (stderr, "expand_reload %s\n", mode_name[mode]);
2102 debug_rtx (operands[0]);
2103 debug_rtx (operands[1]);
2104 #endif
2105
2106 switch (which)
2107 {
2108 case 00: /* Don't know why this gets here. */
2109 case 02: /* general = far */
2110 emit_move_insn (operands[0], operands[1]);
2111 return;
2112
2113 case 10: /* cr = mem */
2114 case 11: /* cr = cr */
2115 case 01: /* mem = cr */
2116 case 12: /* cr = far */
2117 emit_move_insn (operands[2], operands[1]);
2118 emit_move_insn (operands[0], operands[2]);
2119 return;
2120
2121 case 20: /* far = general */
2122 emit_move_insn (operands[2], XEXP (operands[1], 0));
2123 emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2]));
2124 return;
2125
2126 case 21: /* far = cr */
2127 case 22: /* far = far */
2128 default:
2129 fprintf (stderr, "unsupported expand reload case %02d for mode %s\n",
2130 which, mode_name[mode]);
2131 debug_rtx (operands[0]);
2132 debug_rtx (operands[1]);
2133 gcc_unreachable ();
2134 }
2135 }
2136
2137 /* Implement PREFERRED_RELOAD_CLASS. See whether X is a constant that
2138 can be moved directly into registers 0 to 7, but not into the rest.
2139 If so, and if the required class includes registers 0 to 7, restrict
2140 it to those registers. */
2141
2142 enum reg_class
2143 mep_preferred_reload_class (rtx x, enum reg_class rclass)
2144 {
2145 switch (GET_CODE (x))
2146 {
2147 case CONST_INT:
2148 if (INTVAL (x) >= 0x10000
2149 && INTVAL (x) < 0x01000000
2150 && (INTVAL (x) & 0xffff) != 0
2151 && reg_class_subset_p (TPREL_REGS, rclass))
2152 rclass = TPREL_REGS;
2153 break;
2154
2155 case CONST:
2156 case SYMBOL_REF:
2157 case LABEL_REF:
2158 if (mep_section_tag (x) != 'f'
2159 && reg_class_subset_p (TPREL_REGS, rclass))
2160 rclass = TPREL_REGS;
2161 break;
2162
2163 default:
2164 break;
2165 }
2166 return rclass;
2167 }
2168 \f
2169 /* Implement REGISTER_MOVE_COST. Return 2 for direct single-register
2170 moves, 4 for direct double-register moves, and 1000 for anything
2171 that requires a temporary register or temporary stack slot. */
2172
2173 int
2174 mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_class to)
2175 {
2176 if (mep_have_copro_copro_moves_p
2177 && reg_class_subset_p (from, CR_REGS)
2178 && reg_class_subset_p (to, CR_REGS))
2179 {
2180 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2181 return 4;
2182 return 2;
2183 }
2184 if (reg_class_subset_p (from, CR_REGS)
2185 && reg_class_subset_p (to, CR_REGS))
2186 {
2187 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2188 return 8;
2189 return 4;
2190 }
2191 if (reg_class_subset_p (from, CR_REGS)
2192 || reg_class_subset_p (to, CR_REGS))
2193 {
2194 if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2195 return 4;
2196 return 2;
2197 }
2198 if (mep_secondary_memory_needed (from, to, mode))
2199 return 1000;
2200 if (MEP_NONGENERAL_CLASS (from) && MEP_NONGENERAL_CLASS (to))
2201 return 1000;
2202
2203 if (GET_MODE_SIZE (mode) > 4)
2204 return 4;
2205
2206 return 2;
2207 }
2208
2209 \f
2210 /* Functions to save and restore machine-specific function data. */
2211
2212 static struct machine_function *
2213 mep_init_machine_status (void)
2214 {
2215 return ggc_alloc_cleared_machine_function ();
2216 }
2217
2218 static rtx
2219 mep_allocate_initial_value (rtx reg)
2220 {
2221 int rss;
2222
2223 if (GET_CODE (reg) != REG)
2224 return NULL_RTX;
2225
2226 if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
2227 return NULL_RTX;
2228
2229 /* In interrupt functions, the "initial" values of $gp and $tp are
2230 provided by the prologue. They are not necessarily the same as
2231 the values that the caller was using. */
2232 if (REGNO (reg) == TP_REGNO || REGNO (reg) == GP_REGNO)
2233 if (mep_interrupt_p ())
2234 return NULL_RTX;
2235
2236 if (! cfun->machine->reg_save_slot[REGNO(reg)])
2237 {
2238 cfun->machine->reg_save_size += 4;
2239 cfun->machine->reg_save_slot[REGNO(reg)] = cfun->machine->reg_save_size;
2240 }
2241
2242 rss = cfun->machine->reg_save_slot[REGNO(reg)];
2243 return gen_rtx_MEM (SImode, plus_constant (Pmode, arg_pointer_rtx, -rss));
2244 }
2245
2246 rtx
2247 mep_return_addr_rtx (int count)
2248 {
2249 if (count != 0)
2250 return const0_rtx;
2251
2252 return get_hard_reg_initial_val (Pmode, LP_REGNO);
2253 }
2254
2255 static rtx
2256 mep_tp_rtx (void)
2257 {
2258 return get_hard_reg_initial_val (Pmode, TP_REGNO);
2259 }
2260
2261 static rtx
2262 mep_gp_rtx (void)
2263 {
2264 return get_hard_reg_initial_val (Pmode, GP_REGNO);
2265 }
2266
2267 static bool
2268 mep_interrupt_p (void)
2269 {
2270 if (cfun->machine->interrupt_handler == 0)
2271 {
2272 int interrupt_handler
2273 = (lookup_attribute ("interrupt",
2274 DECL_ATTRIBUTES (current_function_decl))
2275 != NULL_TREE);
2276 cfun->machine->interrupt_handler = interrupt_handler ? 2 : 1;
2277 }
2278 return cfun->machine->interrupt_handler == 2;
2279 }
2280
2281 static bool
2282 mep_disinterrupt_p (void)
2283 {
2284 if (cfun->machine->disable_interrupts == 0)
2285 {
2286 int disable_interrupts
2287 = (lookup_attribute ("disinterrupt",
2288 DECL_ATTRIBUTES (current_function_decl))
2289 != NULL_TREE);
2290 cfun->machine->disable_interrupts = disable_interrupts ? 2 : 1;
2291 }
2292 return cfun->machine->disable_interrupts == 2;
2293 }
2294
2295 \f
2296 /* Frame/Epilog/Prolog Related. */
2297
2298 static bool
2299 mep_reg_set_p (rtx reg, rtx insn)
2300 {
2301 /* Similar to reg_set_p in rtlanal.c, but we ignore calls */
2302 if (INSN_P (insn))
2303 {
2304 if (FIND_REG_INC_NOTE (insn, reg))
2305 return true;
2306 insn = PATTERN (insn);
2307 }
2308
2309 if (GET_CODE (insn) == SET
2310 && GET_CODE (XEXP (insn, 0)) == REG
2311 && GET_CODE (XEXP (insn, 1)) == REG
2312 && REGNO (XEXP (insn, 0)) == REGNO (XEXP (insn, 1)))
2313 return false;
2314
2315 return set_of (reg, insn) != NULL_RTX;
2316 }
2317
2318
2319 #define MEP_SAVES_UNKNOWN 0
2320 #define MEP_SAVES_YES 1
2321 #define MEP_SAVES_MAYBE 2
2322 #define MEP_SAVES_NO 3
2323
2324 static bool
2325 mep_reg_set_in_function (int regno)
2326 {
2327 rtx reg, insn;
2328
2329 if (mep_interrupt_p () && df_regs_ever_live_p(regno))
2330 return true;
2331
2332 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2333 return true;
2334
2335 push_topmost_sequence ();
2336 insn = get_insns ();
2337 pop_topmost_sequence ();
2338
2339 if (!insn)
2340 return false;
2341
2342 reg = gen_rtx_REG (SImode, regno);
2343
2344 for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
2345 if (INSN_P (insn) && mep_reg_set_p (reg, insn))
2346 return true;
2347 return false;
2348 }
2349
2350 static bool
2351 mep_asm_without_operands_p (void)
2352 {
2353 if (cfun->machine->asms_without_operands == 0)
2354 {
2355 rtx insn;
2356
2357 push_topmost_sequence ();
2358 insn = get_insns ();
2359 pop_topmost_sequence ();
2360
2361 cfun->machine->asms_without_operands = 1;
2362 while (insn)
2363 {
2364 if (INSN_P (insn)
2365 && GET_CODE (PATTERN (insn)) == ASM_INPUT)
2366 {
2367 cfun->machine->asms_without_operands = 2;
2368 break;
2369 }
2370 insn = NEXT_INSN (insn);
2371 }
2372
2373 }
2374 return cfun->machine->asms_without_operands == 2;
2375 }
2376
2377 /* Interrupt functions save/restore every call-preserved register, and
2378 any call-used register it uses (or all if it calls any function,
2379 since they may get clobbered there too). Here we check to see
2380 which call-used registers need saving. */
2381
2382 #define IVC2_ISAVED_REG(r) (TARGET_IVC2 \
2383 && (r == FIRST_CCR_REGNO + 1 \
2384 || (r >= FIRST_CCR_REGNO + 8 && r <= FIRST_CCR_REGNO + 11) \
2385 || (r >= FIRST_CCR_REGNO + 16 && r <= FIRST_CCR_REGNO + 31)))
2386
2387 static bool
2388 mep_interrupt_saved_reg (int r)
2389 {
2390 if (!mep_interrupt_p ())
2391 return false;
2392 if (r == REGSAVE_CONTROL_TEMP
2393 || (TARGET_64BIT_CR_REGS && TARGET_COP && r == REGSAVE_CONTROL_TEMP+1))
2394 return true;
2395 if (mep_asm_without_operands_p ()
2396 && (!fixed_regs[r]
2397 || (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO || r == LP_REGNO)
2398 || IVC2_ISAVED_REG (r)))
2399 return true;
2400 if (!crtl->is_leaf)
2401 /* Function calls mean we need to save $lp. */
2402 if (r == LP_REGNO || IVC2_ISAVED_REG (r))
2403 return true;
2404 if (!crtl->is_leaf || cfun->machine->doloop_tags > 0)
2405 /* The interrupt handler might use these registers for repeat blocks,
2406 or it might call a function that does so. */
2407 if (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO)
2408 return true;
2409 if (crtl->is_leaf && call_used_regs[r] && !df_regs_ever_live_p(r))
2410 return false;
2411 /* Functions we call might clobber these. */
2412 if (call_used_regs[r] && !fixed_regs[r])
2413 return true;
2414 /* Additional registers that need to be saved for IVC2. */
2415 if (IVC2_ISAVED_REG (r))
2416 return true;
2417
2418 return false;
2419 }
2420
2421 static bool
2422 mep_call_saves_register (int r)
2423 {
2424 if (! cfun->machine->frame_locked)
2425 {
2426 int rv = MEP_SAVES_NO;
2427
2428 if (cfun->machine->reg_save_slot[r])
2429 rv = MEP_SAVES_YES;
2430 else if (r == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2431 rv = MEP_SAVES_YES;
2432 else if (r == FRAME_POINTER_REGNUM && frame_pointer_needed)
2433 rv = MEP_SAVES_YES;
2434 else if ((!call_used_regs[r] || r == LP_REGNO) && df_regs_ever_live_p(r))
2435 rv = MEP_SAVES_YES;
2436 else if (crtl->calls_eh_return && (r == 10 || r == 11))
2437 /* We need these to have stack slots so that they can be set during
2438 unwinding. */
2439 rv = MEP_SAVES_YES;
2440 else if (mep_interrupt_saved_reg (r))
2441 rv = MEP_SAVES_YES;
2442 cfun->machine->reg_saved[r] = rv;
2443 }
2444 return cfun->machine->reg_saved[r] == MEP_SAVES_YES;
2445 }
2446
2447 /* Return true if epilogue uses register REGNO. */
2448
2449 bool
2450 mep_epilogue_uses (int regno)
2451 {
2452 /* Since $lp is a call-saved register, the generic code will normally
2453 mark it used in the epilogue if it needs to be saved and restored.
2454 However, when profiling is enabled, the profiling code will implicitly
2455 clobber $11. This case has to be handled specially both here and in
2456 mep_call_saves_register. */
2457 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2458 return true;
2459 /* Interrupt functions save/restore pretty much everything. */
2460 return (reload_completed && mep_interrupt_saved_reg (regno));
2461 }
2462
2463 static int
2464 mep_reg_size (int regno)
2465 {
2466 if (CR_REGNO_P (regno) && TARGET_64BIT_CR_REGS)
2467 return 8;
2468 return 4;
2469 }
2470
2471 /* Worker function for TARGET_CAN_ELIMINATE. */
2472
2473 bool
2474 mep_can_eliminate (const int from, const int to)
2475 {
2476 return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
2477 ? ! frame_pointer_needed
2478 : true);
2479 }
2480
2481 int
2482 mep_elimination_offset (int from, int to)
2483 {
2484 int reg_save_size;
2485 int i;
2486 int frame_size = get_frame_size () + crtl->outgoing_args_size;
2487 int total_size;
2488
2489 if (!cfun->machine->frame_locked)
2490 memset (cfun->machine->reg_saved, 0, sizeof (cfun->machine->reg_saved));
2491
2492 /* We don't count arg_regs_to_save in the arg pointer offset, because
2493 gcc thinks the arg pointer has moved along with the saved regs.
2494 However, we do count it when we adjust $sp in the prologue. */
2495 reg_save_size = 0;
2496 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2497 if (mep_call_saves_register (i))
2498 reg_save_size += mep_reg_size (i);
2499
2500 if (reg_save_size % 8)
2501 cfun->machine->regsave_filler = 8 - (reg_save_size % 8);
2502 else
2503 cfun->machine->regsave_filler = 0;
2504
2505 /* This is what our total stack adjustment looks like. */
2506 total_size = (reg_save_size + frame_size + cfun->machine->regsave_filler);
2507
2508 if (total_size % 8)
2509 cfun->machine->frame_filler = 8 - (total_size % 8);
2510 else
2511 cfun->machine->frame_filler = 0;
2512
2513
2514 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2515 return reg_save_size + cfun->machine->regsave_filler;
2516
2517 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2518 return cfun->machine->frame_filler + frame_size;
2519
2520 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2521 return reg_save_size + cfun->machine->regsave_filler + cfun->machine->frame_filler + frame_size;
2522
2523 gcc_unreachable ();
2524 }
2525
2526 static rtx
2527 F (rtx x)
2528 {
2529 RTX_FRAME_RELATED_P (x) = 1;
2530 return x;
2531 }
2532
2533 /* Since the prologue/epilogue code is generated after optimization,
2534 we can't rely on gcc to split constants for us. So, this code
2535 captures all the ways to add a constant to a register in one logic
2536 chunk, including optimizing away insns we just don't need. This
2537 makes the prolog/epilog code easier to follow. */
2538 static void
2539 add_constant (int dest, int src, int value, int mark_frame)
2540 {
2541 rtx insn;
2542 int hi, lo;
2543
2544 if (src == dest && value == 0)
2545 return;
2546
2547 if (value == 0)
2548 {
2549 insn = emit_move_insn (gen_rtx_REG (SImode, dest),
2550 gen_rtx_REG (SImode, src));
2551 if (mark_frame)
2552 RTX_FRAME_RELATED_P(insn) = 1;
2553 return;
2554 }
2555
2556 if (value >= -32768 && value <= 32767)
2557 {
2558 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2559 gen_rtx_REG (SImode, src),
2560 GEN_INT (value)));
2561 if (mark_frame)
2562 RTX_FRAME_RELATED_P(insn) = 1;
2563 return;
2564 }
2565
2566 /* Big constant, need to use a temp register. We use
2567 REGSAVE_CONTROL_TEMP because it's call clobberable (the reg save
2568 area is always small enough to directly add to). */
2569
2570 hi = trunc_int_for_mode (value & 0xffff0000, SImode);
2571 lo = value & 0xffff;
2572
2573 insn = emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2574 GEN_INT (hi));
2575
2576 if (lo)
2577 {
2578 insn = emit_insn (gen_iorsi3 (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2579 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2580 GEN_INT (lo)));
2581 }
2582
2583 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2584 gen_rtx_REG (SImode, src),
2585 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP)));
2586 if (mark_frame)
2587 {
2588 RTX_FRAME_RELATED_P(insn) = 1;
2589 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2590 gen_rtx_SET (SImode,
2591 gen_rtx_REG (SImode, dest),
2592 gen_rtx_PLUS (SImode,
2593 gen_rtx_REG (SImode, dest),
2594 GEN_INT (value))));
2595 }
2596 }
2597
2598 /* Move SRC to DEST. Mark the move as being potentially dead if
2599 MAYBE_DEAD_P. */
2600
2601 static rtx
2602 maybe_dead_move (rtx dest, rtx src, bool ATTRIBUTE_UNUSED maybe_dead_p)
2603 {
2604 rtx insn = emit_move_insn (dest, src);
2605 #if 0
2606 if (maybe_dead_p)
2607 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
2608 #endif
2609 return insn;
2610 }
2611
2612 /* Used for interrupt functions, which can't assume that $tp and $gp
2613 contain the correct pointers. */
2614
2615 static void
2616 mep_reload_pointer (int regno, const char *symbol)
2617 {
2618 rtx reg, sym;
2619
2620 if (!df_regs_ever_live_p(regno) && crtl->is_leaf)
2621 return;
2622
2623 reg = gen_rtx_REG (SImode, regno);
2624 sym = gen_rtx_SYMBOL_REF (SImode, symbol);
2625 emit_insn (gen_movsi_topsym_s (reg, sym));
2626 emit_insn (gen_movsi_botsym_s (reg, reg, sym));
2627 }
2628
2629 /* Assign save slots for any register not already saved. DImode
2630 registers go at the end of the reg save area; the rest go at the
2631 beginning. This is for alignment purposes. Returns true if a frame
2632 is really needed. */
2633 static bool
2634 mep_assign_save_slots (int reg_save_size)
2635 {
2636 bool really_need_stack_frame = false;
2637 int di_ofs = 0;
2638 int i;
2639
2640 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2641 if (mep_call_saves_register(i))
2642 {
2643 int regsize = mep_reg_size (i);
2644
2645 if ((i != TP_REGNO && i != GP_REGNO && i != LP_REGNO)
2646 || mep_reg_set_in_function (i))
2647 really_need_stack_frame = true;
2648
2649 if (cfun->machine->reg_save_slot[i])
2650 continue;
2651
2652 if (regsize < 8)
2653 {
2654 cfun->machine->reg_save_size += regsize;
2655 cfun->machine->reg_save_slot[i] = cfun->machine->reg_save_size;
2656 }
2657 else
2658 {
2659 cfun->machine->reg_save_slot[i] = reg_save_size - di_ofs;
2660 di_ofs += 8;
2661 }
2662 }
2663 cfun->machine->frame_locked = 1;
2664 return really_need_stack_frame;
2665 }
2666
2667 void
2668 mep_expand_prologue (void)
2669 {
2670 int i, rss, sp_offset = 0;
2671 int reg_save_size;
2672 int frame_size;
2673 int really_need_stack_frame;
2674
2675 /* We must not allow register renaming in interrupt functions,
2676 because that invalidates the correctness of the set of call-used
2677 registers we're going to save/restore. */
2678 mep_set_leaf_registers (mep_interrupt_p () ? 0 : 1);
2679
2680 if (mep_disinterrupt_p ())
2681 emit_insn (gen_mep_disable_int ());
2682
2683 cfun->machine->mep_frame_pointer_needed = frame_pointer_needed;
2684
2685 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2686 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2687 really_need_stack_frame = frame_size;
2688
2689 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2690
2691 sp_offset = reg_save_size;
2692 if (sp_offset + frame_size < 128)
2693 sp_offset += frame_size ;
2694
2695 add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2696
2697 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2698 if (mep_call_saves_register(i))
2699 {
2700 rtx mem;
2701 bool maybe_dead_p;
2702 enum machine_mode rmode;
2703
2704 rss = cfun->machine->reg_save_slot[i];
2705
2706 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2707 && (!mep_reg_set_in_function (i)
2708 && !mep_interrupt_p ()))
2709 continue;
2710
2711 if (mep_reg_size (i) == 8)
2712 rmode = DImode;
2713 else
2714 rmode = SImode;
2715
2716 /* If there is a pseudo associated with this register's initial value,
2717 reload might have already spilt it to the stack slot suggested by
2718 ALLOCATE_INITIAL_VALUE. The moves emitted here can then be safely
2719 deleted as dead. */
2720 mem = gen_rtx_MEM (rmode,
2721 plus_constant (Pmode, stack_pointer_rtx,
2722 sp_offset - rss));
2723 maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2724
2725 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2726 F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2727 else if (rmode == DImode)
2728 {
2729 rtx insn;
2730 int be = TARGET_BIG_ENDIAN ? 4 : 0;
2731
2732 mem = gen_rtx_MEM (SImode,
2733 plus_constant (Pmode, stack_pointer_rtx,
2734 sp_offset - rss + be));
2735
2736 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2737 gen_rtx_REG (SImode, i),
2738 maybe_dead_p);
2739 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2740 gen_rtx_ZERO_EXTRACT (SImode,
2741 gen_rtx_REG (DImode, i),
2742 GEN_INT (32),
2743 GEN_INT (32)),
2744 maybe_dead_p);
2745 insn = maybe_dead_move (mem,
2746 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2747 maybe_dead_p);
2748 RTX_FRAME_RELATED_P (insn) = 1;
2749
2750 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2751 gen_rtx_SET (VOIDmode,
2752 copy_rtx (mem),
2753 gen_rtx_REG (rmode, i)));
2754 mem = gen_rtx_MEM (SImode,
2755 plus_constant (Pmode, stack_pointer_rtx,
2756 sp_offset - rss + (4-be)));
2757 insn = maybe_dead_move (mem,
2758 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2759 maybe_dead_p);
2760 }
2761 else
2762 {
2763 rtx insn;
2764 maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2765 gen_rtx_REG (rmode, i),
2766 maybe_dead_p);
2767 insn = maybe_dead_move (mem,
2768 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2769 maybe_dead_p);
2770 RTX_FRAME_RELATED_P (insn) = 1;
2771
2772 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2773 gen_rtx_SET (VOIDmode,
2774 copy_rtx (mem),
2775 gen_rtx_REG (rmode, i)));
2776 }
2777 }
2778
2779 if (frame_pointer_needed)
2780 {
2781 /* We've already adjusted down by sp_offset. Total $sp change
2782 is reg_save_size + frame_size. We want a net change here of
2783 just reg_save_size. */
2784 add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2785 }
2786
2787 add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2788
2789 if (mep_interrupt_p ())
2790 {
2791 mep_reload_pointer(GP_REGNO, "__sdabase");
2792 mep_reload_pointer(TP_REGNO, "__tpbase");
2793 }
2794 }
2795
2796 static void
2797 mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2798 {
2799 int local = hwi_local;
2800 int frame_size = local + crtl->outgoing_args_size;
2801 int reg_save_size;
2802 int ffill;
2803 int i, sp, skip;
2804 int sp_offset;
2805 int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2806
2807 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2808 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2809 sp_offset = reg_save_size + frame_size;
2810
2811 ffill = cfun->machine->frame_filler;
2812
2813 if (cfun->machine->mep_frame_pointer_needed)
2814 reg_names[FP_REGNO] = "$fp";
2815 else
2816 reg_names[FP_REGNO] = "$8";
2817
2818 if (sp_offset == 0)
2819 return;
2820
2821 if (debug_info_level == DINFO_LEVEL_NONE)
2822 {
2823 fprintf (file, "\t# frame: %d", sp_offset);
2824 if (reg_save_size)
2825 fprintf (file, " %d regs", reg_save_size);
2826 if (local)
2827 fprintf (file, " %d locals", local);
2828 if (crtl->outgoing_args_size)
2829 fprintf (file, " %d args", crtl->outgoing_args_size);
2830 fprintf (file, "\n");
2831 return;
2832 }
2833
2834 fprintf (file, "\t#\n");
2835 fprintf (file, "\t# Initial Frame Information:\n");
2836 if (sp_offset || !frame_pointer_needed)
2837 fprintf (file, "\t# Entry ---------- 0\n");
2838
2839 /* Sort registers by save slots, so they're printed in the order
2840 they appear in memory, not the order they're saved in. */
2841 for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
2842 slot_map[si] = si;
2843 for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
2844 for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
2845 if (cfun->machine->reg_save_slot[slot_map[si]]
2846 > cfun->machine->reg_save_slot[slot_map[sj]])
2847 {
2848 int t = slot_map[si];
2849 slot_map[si] = slot_map[sj];
2850 slot_map[sj] = t;
2851 }
2852
2853 sp = 0;
2854 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2855 {
2856 int rsize;
2857 int r = slot_map[i];
2858 int rss = cfun->machine->reg_save_slot[r];
2859
2860 if (!mep_call_saves_register (r))
2861 continue;
2862
2863 if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
2864 && (!mep_reg_set_in_function (r)
2865 && !mep_interrupt_p ()))
2866 continue;
2867
2868 rsize = mep_reg_size(r);
2869 skip = rss - (sp+rsize);
2870 if (skip)
2871 fprintf (file, "\t# %3d bytes for alignment\n", skip);
2872 fprintf (file, "\t# %3d bytes for saved %-3s %3d($sp)\n",
2873 rsize, reg_names[r], sp_offset - rss);
2874 sp = rss;
2875 }
2876
2877 skip = reg_save_size - sp;
2878 if (skip)
2879 fprintf (file, "\t# %3d bytes for alignment\n", skip);
2880
2881 if (frame_pointer_needed)
2882 fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
2883 if (local)
2884 fprintf (file, "\t# %3d bytes for local vars\n", local);
2885 if (ffill)
2886 fprintf (file, "\t# %3d bytes for alignment\n", ffill);
2887 if (crtl->outgoing_args_size)
2888 fprintf (file, "\t# %3d bytes for outgoing args\n",
2889 crtl->outgoing_args_size);
2890 fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
2891 fprintf (file, "\t#\n");
2892 }
2893
2894
2895 static int mep_prevent_lp_restore = 0;
2896 static int mep_sibcall_epilogue = 0;
2897
2898 void
2899 mep_expand_epilogue (void)
2900 {
2901 int i, sp_offset = 0;
2902 int reg_save_size = 0;
2903 int frame_size;
2904 int lp_temp = LP_REGNO, lp_slot = -1;
2905 int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
2906 int interrupt_handler = mep_interrupt_p ();
2907
2908 if (profile_arc_flag == 2)
2909 emit_insn (gen_mep_bb_trace_ret ());
2910
2911 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2912 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2913
2914 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2915
2916 if (frame_pointer_needed)
2917 {
2918 /* If we have a frame pointer, we won't have a reliable stack
2919 pointer (alloca, you know), so rebase SP from FP */
2920 emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
2921 gen_rtx_REG (SImode, FP_REGNO));
2922 sp_offset = reg_save_size;
2923 }
2924 else
2925 {
2926 /* SP is right under our local variable space. Adjust it if
2927 needed. */
2928 sp_offset = reg_save_size + frame_size;
2929 if (sp_offset >= 128)
2930 {
2931 add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
2932 sp_offset -= frame_size;
2933 }
2934 }
2935
2936 /* This is backwards so that we restore the control and coprocessor
2937 registers before the temporary registers we use to restore
2938 them. */
2939 for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
2940 if (mep_call_saves_register (i))
2941 {
2942 enum machine_mode rmode;
2943 int rss = cfun->machine->reg_save_slot[i];
2944
2945 if (mep_reg_size (i) == 8)
2946 rmode = DImode;
2947 else
2948 rmode = SImode;
2949
2950 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2951 && !(mep_reg_set_in_function (i) || interrupt_handler))
2952 continue;
2953 if (mep_prevent_lp_restore && i == LP_REGNO)
2954 continue;
2955 if (!mep_prevent_lp_restore
2956 && !interrupt_handler
2957 && (i == 10 || i == 11))
2958 continue;
2959
2960 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2961 emit_move_insn (gen_rtx_REG (rmode, i),
2962 gen_rtx_MEM (rmode,
2963 plus_constant (Pmode, stack_pointer_rtx,
2964 sp_offset - rss)));
2965 else
2966 {
2967 if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
2968 /* Defer this one so we can jump indirect rather than
2969 copying the RA to $lp and "ret". EH epilogues
2970 automatically skip this anyway. */
2971 lp_slot = sp_offset-rss;
2972 else
2973 {
2974 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2975 gen_rtx_MEM (rmode,
2976 plus_constant (Pmode,
2977 stack_pointer_rtx,
2978 sp_offset-rss)));
2979 emit_move_insn (gen_rtx_REG (rmode, i),
2980 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
2981 }
2982 }
2983 }
2984 if (lp_slot != -1)
2985 {
2986 /* Restore this one last so we know it will be in the temp
2987 register when we return by jumping indirectly via the temp. */
2988 emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2989 gen_rtx_MEM (SImode,
2990 plus_constant (Pmode, stack_pointer_rtx,
2991 lp_slot)));
2992 lp_temp = REGSAVE_CONTROL_TEMP;
2993 }
2994
2995
2996 add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
2997
2998 if (crtl->calls_eh_return && mep_prevent_lp_restore)
2999 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3000 gen_rtx_REG (SImode, SP_REGNO),
3001 cfun->machine->eh_stack_adjust));
3002
3003 if (mep_sibcall_epilogue)
3004 return;
3005
3006 if (mep_disinterrupt_p ())
3007 emit_insn (gen_mep_enable_int ());
3008
3009 if (mep_prevent_lp_restore)
3010 {
3011 emit_jump_insn (gen_eh_return_internal ());
3012 emit_barrier ();
3013 }
3014 else if (interrupt_handler)
3015 emit_jump_insn (gen_mep_reti ());
3016 else
3017 emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3018 }
3019
3020 void
3021 mep_expand_eh_return (rtx *operands)
3022 {
3023 if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3024 {
3025 rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3026 emit_move_insn (ra, operands[0]);
3027 operands[0] = ra;
3028 }
3029
3030 emit_insn (gen_eh_epilogue (operands[0]));
3031 }
3032
3033 void
3034 mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3035 {
3036 cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3037 mep_prevent_lp_restore = 1;
3038 mep_expand_epilogue ();
3039 mep_prevent_lp_restore = 0;
3040 }
3041
3042 void
3043 mep_expand_sibcall_epilogue (void)
3044 {
3045 mep_sibcall_epilogue = 1;
3046 mep_expand_epilogue ();
3047 mep_sibcall_epilogue = 0;
3048 }
3049
3050 static bool
3051 mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3052 {
3053 if (decl == NULL)
3054 return false;
3055
3056 if (mep_section_tag (DECL_RTL (decl)) == 'f')
3057 return false;
3058
3059 /* Can't call to a sibcall from an interrupt or disinterrupt function. */
3060 if (mep_interrupt_p () || mep_disinterrupt_p ())
3061 return false;
3062
3063 return true;
3064 }
3065
3066 rtx
3067 mep_return_stackadj_rtx (void)
3068 {
3069 return gen_rtx_REG (SImode, 10);
3070 }
3071
3072 rtx
3073 mep_return_handler_rtx (void)
3074 {
3075 return gen_rtx_REG (SImode, LP_REGNO);
3076 }
3077
3078 void
3079 mep_function_profiler (FILE *file)
3080 {
3081 /* Always right at the beginning of the function. */
3082 fprintf (file, "\t# mep function profiler\n");
3083 fprintf (file, "\tadd\t$sp, -8\n");
3084 fprintf (file, "\tsw\t$0, ($sp)\n");
3085 fprintf (file, "\tldc\t$0, $lp\n");
3086 fprintf (file, "\tsw\t$0, 4($sp)\n");
3087 fprintf (file, "\tbsr\t__mep_mcount\n");
3088 fprintf (file, "\tlw\t$0, 4($sp)\n");
3089 fprintf (file, "\tstc\t$0, $lp\n");
3090 fprintf (file, "\tlw\t$0, ($sp)\n");
3091 fprintf (file, "\tadd\t$sp, 8\n\n");
3092 }
3093
3094 const char *
3095 mep_emit_bb_trace_ret (void)
3096 {
3097 fprintf (asm_out_file, "\t# end of block profiling\n");
3098 fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3099 fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3100 fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3101 fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3102 fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3103 fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3104 fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3105 fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3106 fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3107 return "";
3108 }
3109
3110 #undef SAVE
3111 #undef RESTORE
3112 \f
3113 /* Operand Printing. */
3114
3115 void
3116 mep_print_operand_address (FILE *stream, rtx address)
3117 {
3118 if (GET_CODE (address) == MEM)
3119 address = XEXP (address, 0);
3120 else
3121 /* cf: gcc.dg/asm-4.c. */
3122 gcc_assert (GET_CODE (address) == REG);
3123
3124 mep_print_operand (stream, address, 0);
3125 }
3126
3127 static struct
3128 {
3129 char code;
3130 const char *pattern;
3131 const char *format;
3132 }
3133 const conversions[] =
3134 {
3135 { 0, "r", "0" },
3136 { 0, "m+ri", "3(2)" },
3137 { 0, "mr", "(1)" },
3138 { 0, "ms", "(1)" },
3139 { 0, "ml", "(1)" },
3140 { 0, "mLrs", "%lo(3)(2)" },
3141 { 0, "mLr+si", "%lo(4+5)(2)" },
3142 { 0, "m+ru2s", "%tpoff(5)(2)" },
3143 { 0, "m+ru3s", "%sdaoff(5)(2)" },
3144 { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3145 { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3146 { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3147 { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3148 { 0, "mi", "(1)" },
3149 { 0, "m+si", "(2+3)" },
3150 { 0, "m+li", "(2+3)" },
3151 { 0, "i", "0" },
3152 { 0, "s", "0" },
3153 { 0, "+si", "1+2" },
3154 { 0, "+u2si", "%tpoff(3+4)" },
3155 { 0, "+u3si", "%sdaoff(3+4)" },
3156 { 0, "l", "0" },
3157 { 'b', "i", "0" },
3158 { 'B', "i", "0" },
3159 { 'U', "i", "0" },
3160 { 'h', "i", "0" },
3161 { 'h', "Hs", "%hi(1)" },
3162 { 'I', "i", "0" },
3163 { 'I', "u2s", "%tpoff(2)" },
3164 { 'I', "u3s", "%sdaoff(2)" },
3165 { 'I', "+u2si", "%tpoff(3+4)" },
3166 { 'I', "+u3si", "%sdaoff(3+4)" },
3167 { 'J', "i", "0" },
3168 { 'P', "mr", "(1\\+),\\0" },
3169 { 'x', "i", "0" },
3170 { 0, 0, 0 }
3171 };
3172
3173 static int
3174 unique_bit_in (HOST_WIDE_INT i)
3175 {
3176 switch (i & 0xff)
3177 {
3178 case 0x01: case 0xfe: return 0;
3179 case 0x02: case 0xfd: return 1;
3180 case 0x04: case 0xfb: return 2;
3181 case 0x08: case 0xf7: return 3;
3182 case 0x10: case 0x7f: return 4;
3183 case 0x20: case 0xbf: return 5;
3184 case 0x40: case 0xdf: return 6;
3185 case 0x80: case 0xef: return 7;
3186 default:
3187 gcc_unreachable ();
3188 }
3189 }
3190
3191 static int
3192 bit_size_for_clip (HOST_WIDE_INT i)
3193 {
3194 int rv;
3195
3196 for (rv = 0; rv < 31; rv ++)
3197 if (((HOST_WIDE_INT) 1 << rv) > i)
3198 return rv + 1;
3199 gcc_unreachable ();
3200 }
3201
3202 /* Print an operand to a assembler instruction. */
3203
3204 void
3205 mep_print_operand (FILE *file, rtx x, int code)
3206 {
3207 int i, j;
3208 const char *real_name;
3209
3210 if (code == '<')
3211 {
3212 /* Print a mnemonic to do CR <- CR moves. Find out which intrinsic
3213 we're using, then skip over the "mep_" part of its name. */
3214 const struct cgen_insn *insn;
3215
3216 if (mep_get_move_insn (mep_cmov, &insn))
3217 fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3218 else
3219 mep_intrinsic_unavailable (mep_cmov);
3220 return;
3221 }
3222 if (code == 'L')
3223 {
3224 switch (GET_CODE (x))
3225 {
3226 case AND:
3227 fputs ("clr", file);
3228 return;
3229 case IOR:
3230 fputs ("set", file);
3231 return;
3232 case XOR:
3233 fputs ("not", file);
3234 return;
3235 default:
3236 output_operand_lossage ("invalid %%L code");
3237 }
3238 }
3239 if (code == 'M')
3240 {
3241 /* Print the second operand of a CR <- CR move. If we're using
3242 a two-operand instruction (i.e., a real cmov), then just print
3243 the operand normally. If we're using a "reg, reg, immediate"
3244 instruction such as caddi3, print the operand followed by a
3245 zero field. If we're using a three-register instruction,
3246 print the operand twice. */
3247 const struct cgen_insn *insn;
3248
3249 mep_print_operand (file, x, 0);
3250 if (mep_get_move_insn (mep_cmov, &insn)
3251 && insn_data[insn->icode].n_operands == 3)
3252 {
3253 fputs (", ", file);
3254 if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3255 mep_print_operand (file, x, 0);
3256 else
3257 mep_print_operand (file, const0_rtx, 0);
3258 }
3259 return;
3260 }
3261
3262 encode_pattern (x);
3263 for (i = 0; conversions[i].pattern; i++)
3264 if (conversions[i].code == code
3265 && strcmp(conversions[i].pattern, pattern) == 0)
3266 {
3267 for (j = 0; conversions[i].format[j]; j++)
3268 if (conversions[i].format[j] == '\\')
3269 {
3270 fputc (conversions[i].format[j+1], file);
3271 j++;
3272 }
3273 else if (ISDIGIT(conversions[i].format[j]))
3274 {
3275 rtx r = patternr[conversions[i].format[j] - '0'];
3276 switch (GET_CODE (r))
3277 {
3278 case REG:
3279 fprintf (file, "%s", reg_names [REGNO (r)]);
3280 break;
3281 case CONST_INT:
3282 switch (code)
3283 {
3284 case 'b':
3285 fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3286 break;
3287 case 'B':
3288 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3289 break;
3290 case 'h':
3291 fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3292 break;
3293 case 'U':
3294 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3295 break;
3296 case 'J':
3297 fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3298 break;
3299 case 'x':
3300 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3301 && !(INTVAL (r) & 0xff))
3302 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3303 else
3304 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3305 break;
3306 case 'I':
3307 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3308 && conversions[i].format[j+1] == 0)
3309 {
3310 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3311 fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3312 }
3313 else
3314 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3315 break;
3316 default:
3317 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3318 break;
3319 }
3320 break;
3321 case CONST_DOUBLE:
3322 fprintf(file, "[const_double 0x%lx]",
3323 (unsigned long) CONST_DOUBLE_HIGH(r));
3324 break;
3325 case SYMBOL_REF:
3326 real_name = targetm.strip_name_encoding (XSTR (r, 0));
3327 assemble_name (file, real_name);
3328 break;
3329 case LABEL_REF:
3330 output_asm_label (r);
3331 break;
3332 default:
3333 fprintf (stderr, "don't know how to print this operand:");
3334 debug_rtx (r);
3335 gcc_unreachable ();
3336 }
3337 }
3338 else
3339 {
3340 if (conversions[i].format[j] == '+'
3341 && (!code || code == 'I')
3342 && ISDIGIT (conversions[i].format[j+1])
3343 && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3344 && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3345 continue;
3346 fputc(conversions[i].format[j], file);
3347 }
3348 break;
3349 }
3350 if (!conversions[i].pattern)
3351 {
3352 error ("unconvertible operand %c %qs", code?code:'-', pattern);
3353 debug_rtx(x);
3354 }
3355
3356 return;
3357 }
3358
3359 void
3360 mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3361 int noperands ATTRIBUTE_UNUSED)
3362 {
3363 /* Despite the fact that MeP is perfectly capable of branching and
3364 doing something else in the same bundle, gcc does jump
3365 optimization *after* scheduling, so we cannot trust the bundling
3366 flags on jump instructions. */
3367 if (GET_MODE (insn) == BImode
3368 && get_attr_slots (insn) != SLOTS_CORE)
3369 fputc ('+', asm_out_file);
3370 }
3371
3372 /* Function args in registers. */
3373
3374 static void
3375 mep_setup_incoming_varargs (cumulative_args_t cum,
3376 enum machine_mode mode ATTRIBUTE_UNUSED,
3377 tree type ATTRIBUTE_UNUSED, int *pretend_size,
3378 int second_time ATTRIBUTE_UNUSED)
3379 {
3380 int nsave = 4 - (get_cumulative_args (cum)->nregs + 1);
3381
3382 if (nsave > 0)
3383 cfun->machine->arg_regs_to_save = nsave;
3384 *pretend_size = nsave * 4;
3385 }
3386
3387 static int
3388 bytesize (const_tree type, enum machine_mode mode)
3389 {
3390 if (mode == BLKmode)
3391 return int_size_in_bytes (type);
3392 return GET_MODE_SIZE (mode);
3393 }
3394
3395 static rtx
3396 mep_expand_builtin_saveregs (void)
3397 {
3398 int bufsize, i, ns;
3399 rtx regbuf;
3400
3401 ns = cfun->machine->arg_regs_to_save;
3402 if (TARGET_IVC2)
3403 {
3404 bufsize = 8 * ((ns + 1) / 2) + 8 * ns;
3405 regbuf = assign_stack_local (SImode, bufsize, 64);
3406 }
3407 else
3408 {
3409 bufsize = ns * 4;
3410 regbuf = assign_stack_local (SImode, bufsize, 32);
3411 }
3412
3413 move_block_from_reg (5-ns, regbuf, ns);
3414
3415 if (TARGET_IVC2)
3416 {
3417 rtx tmp = gen_rtx_MEM (DImode, XEXP (regbuf, 0));
3418 int ofs = 8 * ((ns+1)/2);
3419
3420 for (i=0; i<ns; i++)
3421 {
3422 int rn = (4-ns) + i + 49;
3423 rtx ptr;
3424
3425 ptr = offset_address (tmp, GEN_INT (ofs), 2);
3426 emit_move_insn (ptr, gen_rtx_REG (DImode, rn));
3427 ofs += 8;
3428 }
3429 }
3430 return XEXP (regbuf, 0);
3431 }
3432
3433 #define VECTOR_TYPE_P(t) (TREE_CODE(t) == VECTOR_TYPE)
3434
3435 static tree
3436 mep_build_builtin_va_list (void)
3437 {
3438 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3439 tree record;
3440
3441
3442 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3443
3444 f_next_gp = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3445 get_identifier ("__va_next_gp"), ptr_type_node);
3446 f_next_gp_limit = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3447 get_identifier ("__va_next_gp_limit"),
3448 ptr_type_node);
3449 f_next_cop = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_cop"),
3450 ptr_type_node);
3451 f_next_stack = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_stack"),
3452 ptr_type_node);
3453
3454 DECL_FIELD_CONTEXT (f_next_gp) = record;
3455 DECL_FIELD_CONTEXT (f_next_gp_limit) = record;
3456 DECL_FIELD_CONTEXT (f_next_cop) = record;
3457 DECL_FIELD_CONTEXT (f_next_stack) = record;
3458
3459 TYPE_FIELDS (record) = f_next_gp;
3460 DECL_CHAIN (f_next_gp) = f_next_gp_limit;
3461 DECL_CHAIN (f_next_gp_limit) = f_next_cop;
3462 DECL_CHAIN (f_next_cop) = f_next_stack;
3463
3464 layout_type (record);
3465
3466 return record;
3467 }
3468
3469 static void
3470 mep_expand_va_start (tree valist, rtx nextarg)
3471 {
3472 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3473 tree next_gp, next_gp_limit, next_cop, next_stack;
3474 tree t, u;
3475 int ns;
3476
3477 ns = cfun->machine->arg_regs_to_save;
3478
3479 f_next_gp = TYPE_FIELDS (va_list_type_node);
3480 f_next_gp_limit = DECL_CHAIN (f_next_gp);
3481 f_next_cop = DECL_CHAIN (f_next_gp_limit);
3482 f_next_stack = DECL_CHAIN (f_next_cop);
3483
3484 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3485 NULL_TREE);
3486 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3487 valist, f_next_gp_limit, NULL_TREE);
3488 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3489 NULL_TREE);
3490 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3491 valist, f_next_stack, NULL_TREE);
3492
3493 /* va_list.next_gp = expand_builtin_saveregs (); */
3494 u = make_tree (sizetype, expand_builtin_saveregs ());
3495 u = fold_convert (ptr_type_node, u);
3496 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp, u);
3497 TREE_SIDE_EFFECTS (t) = 1;
3498 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3499
3500 /* va_list.next_gp_limit = va_list.next_gp + 4 * ns; */
3501 u = fold_build_pointer_plus_hwi (u, 4 * ns);
3502 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp_limit, u);
3503 TREE_SIDE_EFFECTS (t) = 1;
3504 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3505
3506 u = fold_build_pointer_plus_hwi (u, 8 * ((ns+1)/2));
3507 /* va_list.next_cop = ROUND_UP(va_list.next_gp_limit,8); */
3508 t = build2 (MODIFY_EXPR, ptr_type_node, next_cop, u);
3509 TREE_SIDE_EFFECTS (t) = 1;
3510 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3511
3512 /* va_list.next_stack = nextarg; */
3513 u = make_tree (ptr_type_node, nextarg);
3514 t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
3515 TREE_SIDE_EFFECTS (t) = 1;
3516 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3517 }
3518
3519 static tree
3520 mep_gimplify_va_arg_expr (tree valist, tree type,
3521 gimple_seq *pre_p,
3522 gimple_seq *post_p ATTRIBUTE_UNUSED)
3523 {
3524 HOST_WIDE_INT size, rsize;
3525 bool by_reference, ivc2_vec;
3526 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3527 tree next_gp, next_gp_limit, next_cop, next_stack;
3528 tree label_sover, label_selse;
3529 tree tmp, res_addr;
3530
3531 ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type);
3532
3533 size = int_size_in_bytes (type);
3534 by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0);
3535
3536 if (by_reference)
3537 {
3538 type = build_pointer_type (type);
3539 size = 4;
3540 }
3541 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
3542
3543 f_next_gp = TYPE_FIELDS (va_list_type_node);
3544 f_next_gp_limit = DECL_CHAIN (f_next_gp);
3545 f_next_cop = DECL_CHAIN (f_next_gp_limit);
3546 f_next_stack = DECL_CHAIN (f_next_cop);
3547
3548 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3549 NULL_TREE);
3550 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3551 valist, f_next_gp_limit, NULL_TREE);
3552 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3553 NULL_TREE);
3554 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3555 valist, f_next_stack, NULL_TREE);
3556
3557 /* if f_next_gp < f_next_gp_limit
3558 IF (VECTOR_P && IVC2)
3559 val = *f_next_cop;
3560 ELSE
3561 val = *f_next_gp;
3562 f_next_gp += 4;
3563 f_next_cop += 8;
3564 else
3565 label_selse:
3566 val = *f_next_stack;
3567 f_next_stack += rsize;
3568 label_sover:
3569 */
3570
3571 label_sover = create_artificial_label (UNKNOWN_LOCATION);
3572 label_selse = create_artificial_label (UNKNOWN_LOCATION);
3573 res_addr = create_tmp_var (ptr_type_node, NULL);
3574
3575 tmp = build2 (GE_EXPR, boolean_type_node, next_gp,
3576 unshare_expr (next_gp_limit));
3577 tmp = build3 (COND_EXPR, void_type_node, tmp,
3578 build1 (GOTO_EXPR, void_type_node,
3579 unshare_expr (label_selse)),
3580 NULL_TREE);
3581 gimplify_and_add (tmp, pre_p);
3582
3583 if (ivc2_vec)
3584 {
3585 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_cop);
3586 gimplify_and_add (tmp, pre_p);
3587 }
3588 else
3589 {
3590 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_gp);
3591 gimplify_and_add (tmp, pre_p);
3592 }
3593
3594 tmp = fold_build_pointer_plus_hwi (unshare_expr (next_gp), 4);
3595 gimplify_assign (unshare_expr (next_gp), tmp, pre_p);
3596
3597 tmp = fold_build_pointer_plus_hwi (unshare_expr (next_cop), 8);
3598 gimplify_assign (unshare_expr (next_cop), tmp, pre_p);
3599
3600 tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (label_sover));
3601 gimplify_and_add (tmp, pre_p);
3602
3603 /* - - */
3604
3605 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_selse));
3606 gimplify_and_add (tmp, pre_p);
3607
3608 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, unshare_expr (next_stack));
3609 gimplify_and_add (tmp, pre_p);
3610
3611 tmp = fold_build_pointer_plus_hwi (unshare_expr (next_stack), rsize);
3612 gimplify_assign (unshare_expr (next_stack), tmp, pre_p);
3613
3614 /* - - */
3615
3616 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_sover));
3617 gimplify_and_add (tmp, pre_p);
3618
3619 res_addr = fold_convert (build_pointer_type (type), res_addr);
3620
3621 if (by_reference)
3622 res_addr = build_va_arg_indirect_ref (res_addr);
3623
3624 return build_va_arg_indirect_ref (res_addr);
3625 }
3626
3627 void
3628 mep_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
3629 rtx libname ATTRIBUTE_UNUSED,
3630 tree fndecl ATTRIBUTE_UNUSED)
3631 {
3632 pcum->nregs = 0;
3633
3634 if (fntype && lookup_attribute ("vliw", TYPE_ATTRIBUTES (fntype)))
3635 pcum->vliw = 1;
3636 else
3637 pcum->vliw = 0;
3638 }
3639
3640 /* The ABI is thus: Arguments are in $1, $2, $3, $4, stack. Arguments
3641 larger than 4 bytes are passed indirectly. Return value in 0,
3642 unless bigger than 4 bytes, then the caller passes a pointer as the
3643 first arg. For varargs, we copy $1..$4 to the stack. */
3644
3645 static rtx
3646 mep_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
3647 const_tree type ATTRIBUTE_UNUSED,
3648 bool named ATTRIBUTE_UNUSED)
3649 {
3650 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3651
3652 /* VOIDmode is a signal for the backend to pass data to the call
3653 expander via the second operand to the call pattern. We use
3654 this to determine whether to use "jsr" or "jsrv". */
3655 if (mode == VOIDmode)
3656 return GEN_INT (cum->vliw);
3657
3658 /* If we havn't run out of argument registers, return the next. */
3659 if (cum->nregs < 4)
3660 {
3661 if (type && TARGET_IVC2 && VECTOR_TYPE_P (type))
3662 return gen_rtx_REG (mode, cum->nregs + 49);
3663 else
3664 return gen_rtx_REG (mode, cum->nregs + 1);
3665 }
3666
3667 /* Otherwise the argument goes on the stack. */
3668 return NULL_RTX;
3669 }
3670
3671 static bool
3672 mep_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
3673 enum machine_mode mode,
3674 const_tree type,
3675 bool named ATTRIBUTE_UNUSED)
3676 {
3677 int size = bytesize (type, mode);
3678
3679 /* This is non-obvious, but yes, large values passed after we've run
3680 out of registers are *still* passed by reference - we put the
3681 address of the parameter on the stack, as well as putting the
3682 parameter itself elsewhere on the stack. */
3683
3684 if (size <= 0 || size > 8)
3685 return true;
3686 if (size <= 4)
3687 return false;
3688 if (TARGET_IVC2 && get_cumulative_args (cum)->nregs < 4
3689 && type != NULL_TREE && VECTOR_TYPE_P (type))
3690 return false;
3691 return true;
3692 }
3693
3694 static void
3695 mep_function_arg_advance (cumulative_args_t pcum,
3696 enum machine_mode mode ATTRIBUTE_UNUSED,
3697 const_tree type ATTRIBUTE_UNUSED,
3698 bool named ATTRIBUTE_UNUSED)
3699 {
3700 get_cumulative_args (pcum)->nregs += 1;
3701 }
3702
3703 bool
3704 mep_return_in_memory (const_tree type, const_tree decl ATTRIBUTE_UNUSED)
3705 {
3706 int size = bytesize (type, BLKmode);
3707 if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3708 return size > 0 && size <= 8 ? 0 : 1;
3709 return size > 0 && size <= 4 ? 0 : 1;
3710 }
3711
3712 static bool
3713 mep_narrow_volatile_bitfield (void)
3714 {
3715 return true;
3716 return false;
3717 }
3718
3719 /* Implement FUNCTION_VALUE. All values are returned in $0. */
3720
3721 rtx
3722 mep_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
3723 {
3724 if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3725 return gen_rtx_REG (TYPE_MODE (type), 48);
3726 return gen_rtx_REG (TYPE_MODE (type), RETURN_VALUE_REGNUM);
3727 }
3728
3729 /* Implement LIBCALL_VALUE, using the same rules as mep_function_value. */
3730
3731 rtx
3732 mep_libcall_value (enum machine_mode mode)
3733 {
3734 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
3735 }
3736
3737 /* Handle pipeline hazards. */
3738
3739 typedef enum { op_none, op_stc, op_fsft, op_ret } op_num;
3740 static const char *opnames[] = { "", "stc", "fsft", "ret" };
3741
3742 static int prev_opcode = 0;
3743
3744 /* This isn't as optimal as it could be, because we don't know what
3745 control register the STC opcode is storing in. We only need to add
3746 the nop if it's the relevant register, but we add it for irrelevant
3747 registers also. */
3748
3749 void
3750 mep_asm_output_opcode (FILE *file, const char *ptr)
3751 {
3752 int this_opcode = op_none;
3753 const char *hazard = 0;
3754
3755 switch (*ptr)
3756 {
3757 case 'f':
3758 if (strncmp (ptr, "fsft", 4) == 0 && !ISGRAPH (ptr[4]))
3759 this_opcode = op_fsft;
3760 break;
3761 case 'r':
3762 if (strncmp (ptr, "ret", 3) == 0 && !ISGRAPH (ptr[3]))
3763 this_opcode = op_ret;
3764 break;
3765 case 's':
3766 if (strncmp (ptr, "stc", 3) == 0 && !ISGRAPH (ptr[3]))
3767 this_opcode = op_stc;
3768 break;
3769 }
3770
3771 if (prev_opcode == op_stc && this_opcode == op_fsft)
3772 hazard = "nop";
3773 if (prev_opcode == op_stc && this_opcode == op_ret)
3774 hazard = "nop";
3775
3776 if (hazard)
3777 fprintf(file, "%s\t# %s-%s hazard\n\t",
3778 hazard, opnames[prev_opcode], opnames[this_opcode]);
3779
3780 prev_opcode = this_opcode;
3781 }
3782
3783 /* Handle attributes. */
3784
3785 static tree
3786 mep_validate_based_tiny (tree *node, tree name, tree args,
3787 int flags ATTRIBUTE_UNUSED, bool *no_add)
3788 {
3789 if (TREE_CODE (*node) != VAR_DECL
3790 && TREE_CODE (*node) != POINTER_TYPE
3791 && TREE_CODE (*node) != TYPE_DECL)
3792 {
3793 warning (0, "%qE attribute only applies to variables", name);
3794 *no_add = true;
3795 }
3796 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3797 {
3798 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3799 {
3800 warning (0, "address region attributes not allowed with auto storage class");
3801 *no_add = true;
3802 }
3803 /* Ignore storage attribute of pointed to variable: char __far * x; */
3804 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3805 {
3806 warning (0, "address region attributes on pointed-to types ignored");
3807 *no_add = true;
3808 }
3809 }
3810
3811 return NULL_TREE;
3812 }
3813
3814 static int
3815 mep_multiple_address_regions (tree list, bool check_section_attr)
3816 {
3817 tree a;
3818 int count_sections = 0;
3819 int section_attr_count = 0;
3820
3821 for (a = list; a; a = TREE_CHAIN (a))
3822 {
3823 if (is_attribute_p ("based", TREE_PURPOSE (a))
3824 || is_attribute_p ("tiny", TREE_PURPOSE (a))
3825 || is_attribute_p ("near", TREE_PURPOSE (a))
3826 || is_attribute_p ("far", TREE_PURPOSE (a))
3827 || is_attribute_p ("io", TREE_PURPOSE (a)))
3828 count_sections ++;
3829 if (check_section_attr)
3830 section_attr_count += is_attribute_p ("section", TREE_PURPOSE (a));
3831 }
3832
3833 if (check_section_attr)
3834 return section_attr_count;
3835 else
3836 return count_sections;
3837 }
3838
3839 #define MEP_ATTRIBUTES(decl) \
3840 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
3841 : DECL_ATTRIBUTES (decl) \
3842 ? (DECL_ATTRIBUTES (decl)) \
3843 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
3844
3845 static tree
3846 mep_validate_near_far (tree *node, tree name, tree args,
3847 int flags ATTRIBUTE_UNUSED, bool *no_add)
3848 {
3849 if (TREE_CODE (*node) != VAR_DECL
3850 && TREE_CODE (*node) != FUNCTION_DECL
3851 && TREE_CODE (*node) != METHOD_TYPE
3852 && TREE_CODE (*node) != POINTER_TYPE
3853 && TREE_CODE (*node) != TYPE_DECL)
3854 {
3855 warning (0, "%qE attribute only applies to variables and functions",
3856 name);
3857 *no_add = true;
3858 }
3859 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3860 {
3861 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3862 {
3863 warning (0, "address region attributes not allowed with auto storage class");
3864 *no_add = true;
3865 }
3866 /* Ignore storage attribute of pointed to variable: char __far * x; */
3867 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3868 {
3869 warning (0, "address region attributes on pointed-to types ignored");
3870 *no_add = true;
3871 }
3872 }
3873 else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0)
3874 {
3875 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
3876 name, DECL_NAME (*node), DECL_SOURCE_LINE (*node));
3877 DECL_ATTRIBUTES (*node) = NULL_TREE;
3878 }
3879 return NULL_TREE;
3880 }
3881
3882 static tree
3883 mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
3884 int flags ATTRIBUTE_UNUSED, bool *no_add)
3885 {
3886 if (TREE_CODE (*node) != FUNCTION_DECL
3887 && TREE_CODE (*node) != METHOD_TYPE)
3888 {
3889 warning (0, "%qE attribute only applies to functions", name);
3890 *no_add = true;
3891 }
3892 return NULL_TREE;
3893 }
3894
3895 static tree
3896 mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
3897 int flags ATTRIBUTE_UNUSED, bool *no_add)
3898 {
3899 tree function_type;
3900
3901 if (TREE_CODE (*node) != FUNCTION_DECL)
3902 {
3903 warning (0, "%qE attribute only applies to functions", name);
3904 *no_add = true;
3905 return NULL_TREE;
3906 }
3907
3908 if (DECL_DECLARED_INLINE_P (*node))
3909 error ("cannot inline interrupt function %qE", DECL_NAME (*node));
3910 DECL_UNINLINABLE (*node) = 1;
3911
3912 function_type = TREE_TYPE (*node);
3913
3914 if (TREE_TYPE (function_type) != void_type_node)
3915 error ("interrupt function must have return type of void");
3916
3917 if (prototype_p (function_type)
3918 && (TREE_VALUE (TYPE_ARG_TYPES (function_type)) != void_type_node
3919 || TREE_CHAIN (TYPE_ARG_TYPES (function_type)) != NULL_TREE))
3920 error ("interrupt function must have no arguments");
3921
3922 return NULL_TREE;
3923 }
3924
3925 static tree
3926 mep_validate_io_cb (tree *node, tree name, tree args,
3927 int flags ATTRIBUTE_UNUSED, bool *no_add)
3928 {
3929 if (TREE_CODE (*node) != VAR_DECL)
3930 {
3931 warning (0, "%qE attribute only applies to variables", name);
3932 *no_add = true;
3933 }
3934
3935 if (args != NULL_TREE)
3936 {
3937 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
3938 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
3939 if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
3940 {
3941 warning (0, "%qE attribute allows only an integer constant argument",
3942 name);
3943 *no_add = true;
3944 }
3945 }
3946
3947 if (*no_add == false && !TARGET_IO_NO_VOLATILE)
3948 TREE_THIS_VOLATILE (*node) = 1;
3949
3950 return NULL_TREE;
3951 }
3952
3953 static tree
3954 mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
3955 int flags ATTRIBUTE_UNUSED, bool *no_add)
3956 {
3957 if (TREE_CODE (*node) != FUNCTION_TYPE
3958 && TREE_CODE (*node) != FUNCTION_DECL
3959 && TREE_CODE (*node) != METHOD_TYPE
3960 && TREE_CODE (*node) != FIELD_DECL
3961 && TREE_CODE (*node) != TYPE_DECL)
3962 {
3963 static int gave_pointer_note = 0;
3964 static int gave_array_note = 0;
3965 static const char * given_type = NULL;
3966
3967 given_type = tree_code_name[TREE_CODE (*node)];
3968 if (TREE_CODE (*node) == POINTER_TYPE)
3969 given_type = "pointers";
3970 if (TREE_CODE (*node) == ARRAY_TYPE)
3971 given_type = "arrays";
3972
3973 if (given_type)
3974 warning (0, "%qE attribute only applies to functions, not %s",
3975 name, given_type);
3976 else
3977 warning (0, "%qE attribute only applies to functions",
3978 name);
3979 *no_add = true;
3980
3981 if (TREE_CODE (*node) == POINTER_TYPE
3982 && !gave_pointer_note)
3983 {
3984 inform (input_location,
3985 "to describe a pointer to a VLIW function, use syntax like this:\n%s",
3986 " typedef int (__vliw *vfuncptr) ();");
3987 gave_pointer_note = 1;
3988 }
3989
3990 if (TREE_CODE (*node) == ARRAY_TYPE
3991 && !gave_array_note)
3992 {
3993 inform (input_location,
3994 "to describe an array of VLIW function pointers, use syntax like this:\n%s",
3995 " typedef int (__vliw *vfuncptr[]) ();");
3996 gave_array_note = 1;
3997 }
3998 }
3999 if (!TARGET_VLIW)
4000 error ("VLIW functions are not allowed without a VLIW configuration");
4001 return NULL_TREE;
4002 }
4003
4004 static const struct attribute_spec mep_attribute_table[11] =
4005 {
4006 /* name min max decl type func handler
4007 affects_type_identity */
4008 { "based", 0, 0, false, false, false, mep_validate_based_tiny, false },
4009 { "tiny", 0, 0, false, false, false, mep_validate_based_tiny, false },
4010 { "near", 0, 0, false, false, false, mep_validate_near_far, false },
4011 { "far", 0, 0, false, false, false, mep_validate_near_far, false },
4012 { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt,
4013 false },
4014 { "interrupt", 0, 0, false, false, false, mep_validate_interrupt, false },
4015 { "io", 0, 1, false, false, false, mep_validate_io_cb, false },
4016 { "cb", 0, 1, false, false, false, mep_validate_io_cb, false },
4017 { "vliw", 0, 0, false, true, false, mep_validate_vliw, false },
4018 { NULL, 0, 0, false, false, false, NULL, false }
4019 };
4020
4021 static bool
4022 mep_function_attribute_inlinable_p (const_tree callee)
4023 {
4024 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee));
4025 if (!attrs) attrs = DECL_ATTRIBUTES (callee);
4026 return (lookup_attribute ("disinterrupt", attrs) == 0
4027 && lookup_attribute ("interrupt", attrs) == 0);
4028 }
4029
4030 static bool
4031 mep_can_inline_p (tree caller, tree callee)
4032 {
4033 if (TREE_CODE (callee) == ADDR_EXPR)
4034 callee = TREE_OPERAND (callee, 0);
4035
4036 if (!mep_vliw_function_p (caller)
4037 && mep_vliw_function_p (callee))
4038 {
4039 return false;
4040 }
4041 return true;
4042 }
4043
4044 #define FUNC_CALL 1
4045 #define FUNC_DISINTERRUPT 2
4046
4047
4048 struct GTY(()) pragma_entry {
4049 int used;
4050 int flag;
4051 const char *funcname;
4052 };
4053 typedef struct pragma_entry pragma_entry;
4054
4055 /* Hash table of farcall-tagged sections. */
4056 static GTY((param_is (pragma_entry))) htab_t pragma_htab;
4057
4058 static int
4059 pragma_entry_eq (const void *p1, const void *p2)
4060 {
4061 const pragma_entry *old = (const pragma_entry *) p1;
4062 const char *new_name = (const char *) p2;
4063
4064 return strcmp (old->funcname, new_name) == 0;
4065 }
4066
4067 static hashval_t
4068 pragma_entry_hash (const void *p)
4069 {
4070 const pragma_entry *old = (const pragma_entry *) p;
4071 return htab_hash_string (old->funcname);
4072 }
4073
4074 static void
4075 mep_note_pragma_flag (const char *funcname, int flag)
4076 {
4077 pragma_entry **slot;
4078
4079 if (!pragma_htab)
4080 pragma_htab = htab_create_ggc (31, pragma_entry_hash,
4081 pragma_entry_eq, NULL);
4082
4083 slot = (pragma_entry **)
4084 htab_find_slot_with_hash (pragma_htab, funcname,
4085 htab_hash_string (funcname), INSERT);
4086
4087 if (!*slot)
4088 {
4089 *slot = ggc_alloc_pragma_entry ();
4090 (*slot)->flag = 0;
4091 (*slot)->used = 0;
4092 (*slot)->funcname = ggc_strdup (funcname);
4093 }
4094 (*slot)->flag |= flag;
4095 }
4096
4097 static bool
4098 mep_lookup_pragma_flag (const char *funcname, int flag)
4099 {
4100 pragma_entry **slot;
4101
4102 if (!pragma_htab)
4103 return false;
4104
4105 if (funcname[0] == '@' && funcname[2] == '.')
4106 funcname += 3;
4107
4108 slot = (pragma_entry **)
4109 htab_find_slot_with_hash (pragma_htab, funcname,
4110 htab_hash_string (funcname), NO_INSERT);
4111 if (slot && *slot && ((*slot)->flag & flag))
4112 {
4113 (*slot)->used |= flag;
4114 return true;
4115 }
4116 return false;
4117 }
4118
4119 bool
4120 mep_lookup_pragma_call (const char *funcname)
4121 {
4122 return mep_lookup_pragma_flag (funcname, FUNC_CALL);
4123 }
4124
4125 void
4126 mep_note_pragma_call (const char *funcname)
4127 {
4128 mep_note_pragma_flag (funcname, FUNC_CALL);
4129 }
4130
4131 bool
4132 mep_lookup_pragma_disinterrupt (const char *funcname)
4133 {
4134 return mep_lookup_pragma_flag (funcname, FUNC_DISINTERRUPT);
4135 }
4136
4137 void
4138 mep_note_pragma_disinterrupt (const char *funcname)
4139 {
4140 mep_note_pragma_flag (funcname, FUNC_DISINTERRUPT);
4141 }
4142
4143 static int
4144 note_unused_pragma_disinterrupt (void **slot, void *data ATTRIBUTE_UNUSED)
4145 {
4146 const pragma_entry *d = (const pragma_entry *)(*slot);
4147
4148 if ((d->flag & FUNC_DISINTERRUPT)
4149 && !(d->used & FUNC_DISINTERRUPT))
4150 warning (0, "\"#pragma disinterrupt %s\" not used", d->funcname);
4151 return 1;
4152 }
4153
4154 void
4155 mep_file_cleanups (void)
4156 {
4157 if (pragma_htab)
4158 htab_traverse (pragma_htab, note_unused_pragma_disinterrupt, NULL);
4159 }
4160
4161 /* These three functions provide a bridge between the pramgas that
4162 affect register classes, and the functions that maintain them. We
4163 can't call those functions directly as pragma handling is part of
4164 the front end and doesn't have direct access to them. */
4165
4166 void
4167 mep_save_register_info (void)
4168 {
4169 save_register_info ();
4170 }
4171
4172 void
4173 mep_reinit_regs (void)
4174 {
4175 reinit_regs ();
4176 }
4177
4178 void
4179 mep_init_regs (void)
4180 {
4181 init_regs ();
4182 }
4183
4184
4185
4186 static int
4187 mep_attrlist_to_encoding (tree list, tree decl)
4188 {
4189 if (mep_multiple_address_regions (list, false) > 1)
4190 {
4191 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
4192 TREE_PURPOSE (TREE_CHAIN (list)),
4193 DECL_NAME (decl),
4194 DECL_SOURCE_LINE (decl));
4195 TREE_CHAIN (list) = NULL_TREE;
4196 }
4197
4198 while (list)
4199 {
4200 if (is_attribute_p ("based", TREE_PURPOSE (list)))
4201 return 'b';
4202 if (is_attribute_p ("tiny", TREE_PURPOSE (list)))
4203 return 't';
4204 if (is_attribute_p ("near", TREE_PURPOSE (list)))
4205 return 'n';
4206 if (is_attribute_p ("far", TREE_PURPOSE (list)))
4207 return 'f';
4208 if (is_attribute_p ("io", TREE_PURPOSE (list)))
4209 {
4210 if (TREE_VALUE (list)
4211 && TREE_VALUE (TREE_VALUE (list))
4212 && TREE_CODE (TREE_VALUE (TREE_VALUE (list))) == INTEGER_CST)
4213 {
4214 int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(list)));
4215 if (location >= 0
4216 && location <= 0x1000000)
4217 return 'i';
4218 }
4219 return 'I';
4220 }
4221 if (is_attribute_p ("cb", TREE_PURPOSE (list)))
4222 return 'c';
4223 list = TREE_CHAIN (list);
4224 }
4225 if (TARGET_TF
4226 && TREE_CODE (decl) == FUNCTION_DECL
4227 && DECL_SECTION_NAME (decl) == 0)
4228 return 'f';
4229 return 0;
4230 }
4231
4232 static int
4233 mep_comp_type_attributes (const_tree t1, const_tree t2)
4234 {
4235 int vliw1, vliw2;
4236
4237 vliw1 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t1)) != 0);
4238 vliw2 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t2)) != 0);
4239
4240 if (vliw1 != vliw2)
4241 return 0;
4242
4243 return 1;
4244 }
4245
4246 static void
4247 mep_insert_attributes (tree decl, tree *attributes)
4248 {
4249 int size;
4250 const char *secname = 0;
4251 tree attrib, attrlist;
4252 char encoding;
4253
4254 if (TREE_CODE (decl) == FUNCTION_DECL)
4255 {
4256 const char *funcname = IDENTIFIER_POINTER (DECL_NAME (decl));
4257
4258 if (mep_lookup_pragma_disinterrupt (funcname))
4259 {
4260 attrib = build_tree_list (get_identifier ("disinterrupt"), NULL_TREE);
4261 *attributes = chainon (*attributes, attrib);
4262 }
4263 }
4264
4265 if (TREE_CODE (decl) != VAR_DECL
4266 || ! (TREE_PUBLIC (decl) || TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
4267 return;
4268
4269 if (TREE_READONLY (decl) && TARGET_DC)
4270 /* -mdc means that const variables default to the near section,
4271 regardless of the size cutoff. */
4272 return;
4273
4274 /* User specified an attribute, so override the default.
4275 Ignore storage attribute of pointed to variable. char __far * x; */
4276 if (! (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE))
4277 {
4278 if (TYPE_P (decl) && TYPE_ATTRIBUTES (decl) && *attributes)
4279 TYPE_ATTRIBUTES (decl) = NULL_TREE;
4280 else if (DECL_ATTRIBUTES (decl) && *attributes)
4281 DECL_ATTRIBUTES (decl) = NULL_TREE;
4282 }
4283
4284 attrlist = *attributes ? *attributes : DECL_ATTRIBUTES (decl);
4285 encoding = mep_attrlist_to_encoding (attrlist, decl);
4286 if (!encoding && TYPE_P (TREE_TYPE (decl)))
4287 {
4288 attrlist = TYPE_ATTRIBUTES (TREE_TYPE (decl));
4289 encoding = mep_attrlist_to_encoding (attrlist, decl);
4290 }
4291 if (encoding)
4292 {
4293 /* This means that the declaration has a specific section
4294 attribute, so we should not apply the default rules. */
4295
4296 if (encoding == 'i' || encoding == 'I')
4297 {
4298 tree attr = lookup_attribute ("io", attrlist);
4299 if (attr
4300 && TREE_VALUE (attr)
4301 && TREE_VALUE (TREE_VALUE(attr)))
4302 {
4303 int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr)));
4304 static tree previous_value = 0;
4305 static int previous_location = 0;
4306 static tree previous_name = 0;
4307
4308 /* We take advantage of the fact that gcc will reuse the
4309 same tree pointer when applying an attribute to a
4310 list of decls, but produce a new tree for attributes
4311 on separate source lines, even when they're textually
4312 identical. This is the behavior we want. */
4313 if (TREE_VALUE (attr) == previous_value
4314 && location == previous_location)
4315 {
4316 warning(0, "__io address 0x%x is the same for %qE and %qE",
4317 location, previous_name, DECL_NAME (decl));
4318 }
4319 previous_name = DECL_NAME (decl);
4320 previous_location = location;
4321 previous_value = TREE_VALUE (attr);
4322 }
4323 }
4324 return;
4325 }
4326
4327
4328 /* Declarations of arrays can change size. Don't trust them. */
4329 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
4330 size = 0;
4331 else
4332 size = int_size_in_bytes (TREE_TYPE (decl));
4333
4334 if (TARGET_RAND_TPGP && size <= 4 && size > 0)
4335 {
4336 if (TREE_PUBLIC (decl)
4337 || DECL_EXTERNAL (decl)
4338 || TREE_STATIC (decl))
4339 {
4340 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
4341 int key = 0;
4342
4343 while (*name)
4344 key += *name++;
4345
4346 switch (key & 3)
4347 {
4348 case 0:
4349 secname = "based";
4350 break;
4351 case 1:
4352 secname = "tiny";
4353 break;
4354 case 2:
4355 secname = "far";
4356 break;
4357 default:
4358 ;
4359 }
4360 }
4361 }
4362 else
4363 {
4364 if (size <= mep_based_cutoff && size > 0)
4365 secname = "based";
4366 else if (size <= mep_tiny_cutoff && size > 0)
4367 secname = "tiny";
4368 else if (TARGET_L)
4369 secname = "far";
4370 }
4371
4372 if (mep_const_section && TREE_READONLY (decl))
4373 {
4374 if (strcmp (mep_const_section, "tiny") == 0)
4375 secname = "tiny";
4376 else if (strcmp (mep_const_section, "near") == 0)
4377 return;
4378 else if (strcmp (mep_const_section, "far") == 0)
4379 secname = "far";
4380 }
4381
4382 if (!secname)
4383 return;
4384
4385 if (!mep_multiple_address_regions (*attributes, true)
4386 && !mep_multiple_address_regions (DECL_ATTRIBUTES (decl), false))
4387 {
4388 attrib = build_tree_list (get_identifier (secname), NULL_TREE);
4389
4390 /* Chain the attribute directly onto the variable's DECL_ATTRIBUTES
4391 in order to avoid the POINTER_TYPE bypasses in mep_validate_near_far
4392 and mep_validate_based_tiny. */
4393 DECL_ATTRIBUTES (decl) = chainon (DECL_ATTRIBUTES (decl), attrib);
4394 }
4395 }
4396
4397 static void
4398 mep_encode_section_info (tree decl, rtx rtl, int first)
4399 {
4400 rtx rtlname;
4401 const char *oldname;
4402 const char *secname;
4403 char encoding;
4404 char *newname;
4405 tree idp;
4406 int maxsize;
4407 tree type;
4408 tree mep_attributes;
4409
4410 if (! first)
4411 return;
4412
4413 if (TREE_CODE (decl) != VAR_DECL
4414 && TREE_CODE (decl) != FUNCTION_DECL)
4415 return;
4416
4417 rtlname = XEXP (rtl, 0);
4418 if (GET_CODE (rtlname) == SYMBOL_REF)
4419 oldname = XSTR (rtlname, 0);
4420 else if (GET_CODE (rtlname) == MEM
4421 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4422 oldname = XSTR (XEXP (rtlname, 0), 0);
4423 else
4424 gcc_unreachable ();
4425
4426 type = TREE_TYPE (decl);
4427 if (type == error_mark_node)
4428 return;
4429 mep_attributes = MEP_ATTRIBUTES (decl);
4430
4431 encoding = mep_attrlist_to_encoding (mep_attributes, decl);
4432
4433 if (encoding)
4434 {
4435 newname = (char *) alloca (strlen (oldname) + 4);
4436 sprintf (newname, "@%c.%s", encoding, oldname);
4437 idp = get_identifier (newname);
4438 XEXP (rtl, 0) =
4439 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4440 SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4441 SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4442
4443 switch (encoding)
4444 {
4445 case 'b':
4446 maxsize = 128;
4447 secname = "based";
4448 break;
4449 case 't':
4450 maxsize = 65536;
4451 secname = "tiny";
4452 break;
4453 case 'n':
4454 maxsize = 0x1000000;
4455 secname = "near";
4456 break;
4457 default:
4458 maxsize = 0;
4459 secname = 0;
4460 break;
4461 }
4462 if (maxsize && int_size_in_bytes (TREE_TYPE (decl)) > maxsize)
4463 {
4464 warning (0, "variable %s (%ld bytes) is too large for the %s section (%d bytes)",
4465 oldname,
4466 (long) int_size_in_bytes (TREE_TYPE (decl)),
4467 secname,
4468 maxsize);
4469 }
4470 }
4471 }
4472
4473 const char *
4474 mep_strip_name_encoding (const char *sym)
4475 {
4476 while (1)
4477 {
4478 if (*sym == '*')
4479 sym++;
4480 else if (*sym == '@' && sym[2] == '.')
4481 sym += 3;
4482 else
4483 return sym;
4484 }
4485 }
4486
4487 static section *
4488 mep_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
4489 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4490 {
4491 int readonly = 1;
4492 int encoding;
4493
4494 switch (TREE_CODE (decl))
4495 {
4496 case VAR_DECL:
4497 if (!TREE_READONLY (decl)
4498 || TREE_SIDE_EFFECTS (decl)
4499 || !DECL_INITIAL (decl)
4500 || (DECL_INITIAL (decl) != error_mark_node
4501 && !TREE_CONSTANT (DECL_INITIAL (decl))))
4502 readonly = 0;
4503 break;
4504 case CONSTRUCTOR:
4505 if (! TREE_CONSTANT (decl))
4506 readonly = 0;
4507 break;
4508
4509 default:
4510 break;
4511 }
4512
4513 if (TREE_CODE (decl) == FUNCTION_DECL)
4514 {
4515 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4516
4517 if (name[0] == '@' && name[2] == '.')
4518 encoding = name[1];
4519 else
4520 encoding = 0;
4521
4522 if (flag_function_sections || DECL_ONE_ONLY (decl))
4523 mep_unique_section (decl, 0);
4524 else if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4525 {
4526 if (encoding == 'f')
4527 return vftext_section;
4528 else
4529 return vtext_section;
4530 }
4531 else if (encoding == 'f')
4532 return ftext_section;
4533 else
4534 return text_section;
4535 }
4536
4537 if (TREE_CODE (decl) == VAR_DECL)
4538 {
4539 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4540
4541 if (name[0] == '@' && name[2] == '.')
4542 switch (name[1])
4543 {
4544 case 'b':
4545 return based_section;
4546
4547 case 't':
4548 if (readonly)
4549 return srodata_section;
4550 if (DECL_INITIAL (decl))
4551 return sdata_section;
4552 return tinybss_section;
4553
4554 case 'f':
4555 if (readonly)
4556 return frodata_section;
4557 return far_section;
4558
4559 case 'i':
4560 case 'I':
4561 error_at (DECL_SOURCE_LOCATION (decl),
4562 "variable %D of type %<io%> must be uninitialized", decl);
4563 return data_section;
4564
4565 case 'c':
4566 error_at (DECL_SOURCE_LOCATION (decl),
4567 "variable %D of type %<cb%> must be uninitialized", decl);
4568 return data_section;
4569 }
4570 }
4571
4572 if (readonly)
4573 return readonly_data_section;
4574
4575 return data_section;
4576 }
4577
4578 static void
4579 mep_unique_section (tree decl, int reloc)
4580 {
4581 static const char *prefixes[][2] =
4582 {
4583 { ".text.", ".gnu.linkonce.t." },
4584 { ".rodata.", ".gnu.linkonce.r." },
4585 { ".data.", ".gnu.linkonce.d." },
4586 { ".based.", ".gnu.linkonce.based." },
4587 { ".sdata.", ".gnu.linkonce.s." },
4588 { ".far.", ".gnu.linkonce.far." },
4589 { ".ftext.", ".gnu.linkonce.ft." },
4590 { ".frodata.", ".gnu.linkonce.frd." },
4591 { ".srodata.", ".gnu.linkonce.srd." },
4592 { ".vtext.", ".gnu.linkonce.v." },
4593 { ".vftext.", ".gnu.linkonce.vf." }
4594 };
4595 int sec = 2; /* .data */
4596 int len;
4597 const char *name, *prefix;
4598 char *string;
4599
4600 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4601 if (DECL_RTL (decl))
4602 name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4603
4604 if (TREE_CODE (decl) == FUNCTION_DECL)
4605 {
4606 if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4607 sec = 9; /* .vtext */
4608 else
4609 sec = 0; /* .text */
4610 }
4611 else if (decl_readonly_section (decl, reloc))
4612 sec = 1; /* .rodata */
4613
4614 if (name[0] == '@' && name[2] == '.')
4615 {
4616 switch (name[1])
4617 {
4618 case 'b':
4619 sec = 3; /* .based */
4620 break;
4621 case 't':
4622 if (sec == 1)
4623 sec = 8; /* .srodata */
4624 else
4625 sec = 4; /* .sdata */
4626 break;
4627 case 'f':
4628 if (sec == 0)
4629 sec = 6; /* .ftext */
4630 else if (sec == 9)
4631 sec = 10; /* .vftext */
4632 else if (sec == 1)
4633 sec = 7; /* .frodata */
4634 else
4635 sec = 5; /* .far. */
4636 break;
4637 }
4638 name += 3;
4639 }
4640
4641 prefix = prefixes[sec][DECL_ONE_ONLY(decl)];
4642 len = strlen (name) + strlen (prefix);
4643 string = (char *) alloca (len + 1);
4644
4645 sprintf (string, "%s%s", prefix, name);
4646
4647 DECL_SECTION_NAME (decl) = build_string (len, string);
4648 }
4649
4650 /* Given a decl, a section name, and whether the decl initializer
4651 has relocs, choose attributes for the section. */
4652
4653 #define SECTION_MEP_VLIW SECTION_MACH_DEP
4654
4655 static unsigned int
4656 mep_section_type_flags (tree decl, const char *name, int reloc)
4657 {
4658 unsigned int flags = default_section_type_flags (decl, name, reloc);
4659
4660 if (decl && TREE_CODE (decl) == FUNCTION_DECL
4661 && lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4662 flags |= SECTION_MEP_VLIW;
4663
4664 return flags;
4665 }
4666
4667 /* Switch to an arbitrary section NAME with attributes as specified
4668 by FLAGS. ALIGN specifies any known alignment requirements for
4669 the section; 0 if the default should be used.
4670
4671 Differs from the standard ELF version only in support of VLIW mode. */
4672
4673 static void
4674 mep_asm_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
4675 {
4676 char flagchars[8], *f = flagchars;
4677 const char *type;
4678
4679 if (!(flags & SECTION_DEBUG))
4680 *f++ = 'a';
4681 if (flags & SECTION_WRITE)
4682 *f++ = 'w';
4683 if (flags & SECTION_CODE)
4684 *f++ = 'x';
4685 if (flags & SECTION_SMALL)
4686 *f++ = 's';
4687 if (flags & SECTION_MEP_VLIW)
4688 *f++ = 'v';
4689 *f = '\0';
4690
4691 if (flags & SECTION_BSS)
4692 type = "nobits";
4693 else
4694 type = "progbits";
4695
4696 fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
4697 name, flagchars, type);
4698
4699 if (flags & SECTION_CODE)
4700 fputs ((flags & SECTION_MEP_VLIW ? "\t.vliw\n" : "\t.core\n"),
4701 asm_out_file);
4702 }
4703
4704 void
4705 mep_output_aligned_common (FILE *stream, tree decl, const char *name,
4706 int size, int align, int global)
4707 {
4708 /* We intentionally don't use mep_section_tag() here. */
4709 if (name[0] == '@'
4710 && (name[1] == 'i' || name[1] == 'I' || name[1] == 'c')
4711 && name[2] == '.')
4712 {
4713 int location = -1;
4714 tree attr = lookup_attribute ((name[1] == 'c' ? "cb" : "io"),
4715 DECL_ATTRIBUTES (decl));
4716 if (attr
4717 && TREE_VALUE (attr)
4718 && TREE_VALUE (TREE_VALUE(attr)))
4719 location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr)));
4720 if (location == -1)
4721 return;
4722 if (global)
4723 {
4724 fprintf (stream, "\t.globl\t");
4725 assemble_name (stream, name);
4726 fprintf (stream, "\n");
4727 }
4728 assemble_name (stream, name);
4729 fprintf (stream, " = %d\n", location);
4730 return;
4731 }
4732 if (name[0] == '@' && name[2] == '.')
4733 {
4734 const char *sec = 0;
4735 switch (name[1])
4736 {
4737 case 'b':
4738 switch_to_section (based_section);
4739 sec = ".based";
4740 break;
4741 case 't':
4742 switch_to_section (tinybss_section);
4743 sec = ".sbss";
4744 break;
4745 case 'f':
4746 switch_to_section (farbss_section);
4747 sec = ".farbss";
4748 break;
4749 }
4750 if (sec)
4751 {
4752 const char *name2;
4753 int p2align = 0;
4754
4755 while (align > BITS_PER_UNIT)
4756 {
4757 align /= 2;
4758 p2align ++;
4759 }
4760 name2 = targetm.strip_name_encoding (name);
4761 if (global)
4762 fprintf (stream, "\t.globl\t%s\n", name2);
4763 fprintf (stream, "\t.p2align %d\n", p2align);
4764 fprintf (stream, "\t.type\t%s,@object\n", name2);
4765 fprintf (stream, "\t.size\t%s,%d\n", name2, size);
4766 fprintf (stream, "%s:\n\t.zero\t%d\n", name2, size);
4767 return;
4768 }
4769 }
4770
4771 if (!global)
4772 {
4773 fprintf (stream, "\t.local\t");
4774 assemble_name (stream, name);
4775 fprintf (stream, "\n");
4776 }
4777 fprintf (stream, "\t.comm\t");
4778 assemble_name (stream, name);
4779 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4780 }
4781
4782 /* Trampolines. */
4783
4784 static void
4785 mep_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
4786 {
4787 rtx addr = XEXP (m_tramp, 0);
4788 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
4789
4790 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__mep_trampoline_helper"),
4791 LCT_NORMAL, VOIDmode, 3,
4792 addr, Pmode,
4793 fnaddr, Pmode,
4794 static_chain, Pmode);
4795 }
4796
4797 /* Experimental Reorg. */
4798
4799 static bool
4800 mep_mentioned_p (rtx in,
4801 rtx reg, /* NULL for mem */
4802 int modes_too) /* if nonzero, modes must match also. */
4803 {
4804 const char *fmt;
4805 int i;
4806 enum rtx_code code;
4807
4808 if (in == 0)
4809 return false;
4810 if (reg && GET_CODE (reg) != REG)
4811 return false;
4812
4813 if (GET_CODE (in) == LABEL_REF)
4814 return (reg == 0);
4815
4816 code = GET_CODE (in);
4817
4818 switch (code)
4819 {
4820 case MEM:
4821 if (reg)
4822 return mep_mentioned_p (XEXP (in, 0), reg, modes_too);
4823 return true;
4824
4825 case REG:
4826 if (!reg)
4827 return false;
4828 if (modes_too && (GET_MODE (in) != GET_MODE (reg)))
4829 return false;
4830 return (REGNO (in) == REGNO (reg));
4831
4832 case SCRATCH:
4833 case CC0:
4834 case PC:
4835 case CONST_INT:
4836 case CONST_DOUBLE:
4837 return false;
4838
4839 default:
4840 break;
4841 }
4842
4843 /* Set's source should be read-only. */
4844 if (code == SET && !reg)
4845 return mep_mentioned_p (SET_DEST (in), reg, modes_too);
4846
4847 fmt = GET_RTX_FORMAT (code);
4848
4849 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4850 {
4851 if (fmt[i] == 'E')
4852 {
4853 register int j;
4854 for (j = XVECLEN (in, i) - 1; j >= 0; j--)
4855 if (mep_mentioned_p (XVECEXP (in, i, j), reg, modes_too))
4856 return true;
4857 }
4858 else if (fmt[i] == 'e'
4859 && mep_mentioned_p (XEXP (in, i), reg, modes_too))
4860 return true;
4861 }
4862 return false;
4863 }
4864
4865 #define EXPERIMENTAL_REGMOVE_REORG 1
4866
4867 #if EXPERIMENTAL_REGMOVE_REORG
4868
4869 static int
4870 mep_compatible_reg_class (int r1, int r2)
4871 {
4872 if (GR_REGNO_P (r1) && GR_REGNO_P (r2))
4873 return 1;
4874 if (CR_REGNO_P (r1) && CR_REGNO_P (r2))
4875 return 1;
4876 return 0;
4877 }
4878
4879 static void
4880 mep_reorg_regmove (rtx insns)
4881 {
4882 rtx insn, next, pat, follow, *where;
4883 int count = 0, done = 0, replace, before = 0;
4884
4885 if (dump_file)
4886 for (insn = insns; insn; insn = NEXT_INSN (insn))
4887 if (GET_CODE (insn) == INSN)
4888 before++;
4889
4890 /* We're looking for (set r2 r1) moves where r1 dies, followed by a
4891 set that uses the r2 and r2 dies there. We replace r2 with r1
4892 and see if it's still a valid insn. If so, delete the first set.
4893 Copied from reorg.c. */
4894
4895 while (!done)
4896 {
4897 done = 1;
4898 for (insn = insns; insn; insn = next)
4899 {
4900 next = next_nonnote_nondebug_insn (insn);
4901 if (GET_CODE (insn) != INSN)
4902 continue;
4903 pat = PATTERN (insn);
4904
4905 replace = 0;
4906
4907 if (GET_CODE (pat) == SET
4908 && GET_CODE (SET_SRC (pat)) == REG
4909 && GET_CODE (SET_DEST (pat)) == REG
4910 && find_regno_note (insn, REG_DEAD, REGNO (SET_SRC (pat)))
4911 && mep_compatible_reg_class (REGNO (SET_SRC (pat)), REGNO (SET_DEST (pat))))
4912 {
4913 follow = next_nonnote_nondebug_insn (insn);
4914 if (dump_file)
4915 fprintf (dump_file, "superfluous moves: considering %d\n", INSN_UID (insn));
4916
4917 while (follow && GET_CODE (follow) == INSN
4918 && GET_CODE (PATTERN (follow)) == SET
4919 && !dead_or_set_p (follow, SET_SRC (pat))
4920 && !mep_mentioned_p (PATTERN (follow), SET_SRC (pat), 0)
4921 && !mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 0))
4922 {
4923 if (dump_file)
4924 fprintf (dump_file, "\tskipping %d\n", INSN_UID (follow));
4925 follow = next_nonnote_insn (follow);
4926 }
4927
4928 if (dump_file)
4929 fprintf (dump_file, "\tfollow is %d\n", INSN_UID (follow));
4930 if (follow && GET_CODE (follow) == INSN
4931 && GET_CODE (PATTERN (follow)) == SET
4932 && find_regno_note (follow, REG_DEAD, REGNO (SET_DEST (pat))))
4933 {
4934 if (GET_CODE (SET_DEST (PATTERN (follow))) == REG)
4935 {
4936 if (mep_mentioned_p (SET_SRC (PATTERN (follow)), SET_DEST (pat), 1))
4937 {
4938 replace = 1;
4939 where = & SET_SRC (PATTERN (follow));
4940 }
4941 }
4942 else if (GET_CODE (SET_DEST (PATTERN (follow))) == MEM)
4943 {
4944 if (mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 1))
4945 {
4946 replace = 1;
4947 where = & PATTERN (follow);
4948 }
4949 }
4950 }
4951 }
4952
4953 /* If so, follow is the corresponding insn */
4954 if (replace)
4955 {
4956 if (dump_file)
4957 {
4958 rtx x;
4959
4960 fprintf (dump_file, "----- Candidate for superfluous move deletion:\n\n");
4961 for (x = insn; x ;x = NEXT_INSN (x))
4962 {
4963 print_rtl_single (dump_file, x);
4964 if (x == follow)
4965 break;
4966 fprintf (dump_file, "\n");
4967 }
4968 }
4969
4970 if (validate_replace_rtx_subexp (SET_DEST (pat), SET_SRC (pat),
4971 follow, where))
4972 {
4973 count ++;
4974 delete_insn (insn);
4975 if (dump_file)
4976 {
4977 fprintf (dump_file, "\n----- Success! new insn:\n\n");
4978 print_rtl_single (dump_file, follow);
4979 }
4980 done = 0;
4981 }
4982 }
4983 }
4984 }
4985
4986 if (dump_file)
4987 {
4988 fprintf (dump_file, "\n%d insn%s deleted out of %d.\n\n", count, count == 1 ? "" : "s", before);
4989 fprintf (dump_file, "=====\n");
4990 }
4991 }
4992 #endif
4993
4994
4995 /* Figure out where to put LABEL, which is the label for a repeat loop.
4996 If INCLUDING, LAST_INSN is the last instruction in the loop, otherwise
4997 the loop ends just before LAST_INSN. If SHARED, insns other than the
4998 "repeat" might use LABEL to jump to the loop's continuation point.
4999
5000 Return the last instruction in the adjusted loop. */
5001
5002 static rtx
5003 mep_insert_repeat_label_last (rtx last_insn, rtx label, bool including,
5004 bool shared)
5005 {
5006 rtx next, prev;
5007 int count = 0, code, icode;
5008
5009 if (dump_file)
5010 fprintf (dump_file, "considering end of repeat loop at insn %d\n",
5011 INSN_UID (last_insn));
5012
5013 /* Set PREV to the last insn in the loop. */
5014 prev = last_insn;
5015 if (!including)
5016 prev = PREV_INSN (prev);
5017
5018 /* Set NEXT to the next insn after the repeat label. */
5019 next = last_insn;
5020 if (!shared)
5021 while (prev != 0)
5022 {
5023 code = GET_CODE (prev);
5024 if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER)
5025 break;
5026
5027 if (INSN_P (prev))
5028 {
5029 if (GET_CODE (PATTERN (prev)) == SEQUENCE)
5030 prev = XVECEXP (PATTERN (prev), 0, 1);
5031
5032 /* Other insns that should not be in the last two opcodes. */
5033 icode = recog_memoized (prev);
5034 if (icode < 0
5035 || icode == CODE_FOR_repeat
5036 || icode == CODE_FOR_erepeat
5037 || get_attr_may_trap (prev) == MAY_TRAP_YES)
5038 break;
5039
5040 /* That leaves JUMP_INSN and INSN. It will have BImode if it
5041 is the second instruction in a VLIW bundle. In that case,
5042 loop again: if the first instruction also satisfies the
5043 conditions above then we will reach here again and put
5044 both of them into the repeat epilogue. Otherwise both
5045 should remain outside. */
5046 if (GET_MODE (prev) != BImode)
5047 {
5048 count++;
5049 next = prev;
5050 if (dump_file)
5051 print_rtl_single (dump_file, next);
5052 if (count == 2)
5053 break;
5054 }
5055 }
5056 prev = PREV_INSN (prev);
5057 }
5058
5059 /* See if we're adding the label immediately after the repeat insn.
5060 If so, we need to separate them with a nop. */
5061 prev = prev_real_insn (next);
5062 if (prev)
5063 switch (recog_memoized (prev))
5064 {
5065 case CODE_FOR_repeat:
5066 case CODE_FOR_erepeat:
5067 if (dump_file)
5068 fprintf (dump_file, "Adding nop inside loop\n");
5069 emit_insn_before (gen_nop (), next);
5070 break;
5071
5072 default:
5073 break;
5074 }
5075
5076 /* Insert the label. */
5077 emit_label_before (label, next);
5078
5079 /* Insert the nops. */
5080 if (dump_file && count < 2)
5081 fprintf (dump_file, "Adding %d nop%s\n\n",
5082 2 - count, count == 1 ? "" : "s");
5083
5084 for (; count < 2; count++)
5085 if (including)
5086 last_insn = emit_insn_after (gen_nop (), last_insn);
5087 else
5088 emit_insn_before (gen_nop (), last_insn);
5089
5090 return last_insn;
5091 }
5092
5093
5094 void
5095 mep_emit_doloop (rtx *operands, int is_end)
5096 {
5097 rtx tag;
5098
5099 if (cfun->machine->doloop_tags == 0
5100 || cfun->machine->doloop_tag_from_end == is_end)
5101 {
5102 cfun->machine->doloop_tags++;
5103 cfun->machine->doloop_tag_from_end = is_end;
5104 }
5105
5106 tag = GEN_INT (cfun->machine->doloop_tags - 1);
5107 if (is_end)
5108 emit_jump_insn (gen_doloop_end_internal (operands[0], operands[4], tag));
5109 else
5110 emit_insn (gen_doloop_begin_internal (operands[0], operands[0], tag));
5111 }
5112
5113
5114 /* Code for converting doloop_begins and doloop_ends into valid
5115 MeP instructions. A doloop_begin is just a placeholder:
5116
5117 $count = unspec ($count)
5118
5119 where $count is initially the number of iterations - 1.
5120 doloop_end has the form:
5121
5122 if ($count-- == 0) goto label
5123
5124 The counter variable is private to the doloop insns, nothing else
5125 relies on its value.
5126
5127 There are three cases, in decreasing order of preference:
5128
5129 1. A loop has exactly one doloop_begin and one doloop_end.
5130 The doloop_end branches to the first instruction after
5131 the doloop_begin.
5132
5133 In this case we can replace the doloop_begin with a repeat
5134 instruction and remove the doloop_end. I.e.:
5135
5136 $count1 = unspec ($count1)
5137 label:
5138 ...
5139 insn1
5140 insn2
5141 if ($count2-- == 0) goto label
5142
5143 becomes:
5144
5145 repeat $count1,repeat_label
5146 label:
5147 ...
5148 repeat_label:
5149 insn1
5150 insn2
5151 # end repeat
5152
5153 2. As for (1), except there are several doloop_ends. One of them
5154 (call it X) falls through to a label L. All the others fall
5155 through to branches to L.
5156
5157 In this case, we remove X and replace the other doloop_ends
5158 with branches to the repeat label. For example:
5159
5160 $count1 = unspec ($count1)
5161 start:
5162 ...
5163 if ($count2-- == 0) goto label
5164 end:
5165 ...
5166 if ($count3-- == 0) goto label
5167 goto end
5168
5169 becomes:
5170
5171 repeat $count1,repeat_label
5172 start:
5173 ...
5174 repeat_label:
5175 nop
5176 nop
5177 # end repeat
5178 end:
5179 ...
5180 goto repeat_label
5181
5182 3. The fallback case. Replace doloop_begins with:
5183
5184 $count = $count + 1
5185
5186 Replace doloop_ends with the equivalent of:
5187
5188 $count = $count - 1
5189 if ($count == 0) goto label
5190
5191 Note that this might need a scratch register if $count
5192 is stored in memory. */
5193
5194 /* A structure describing one doloop_begin. */
5195 struct mep_doloop_begin {
5196 /* The next doloop_begin with the same tag. */
5197 struct mep_doloop_begin *next;
5198
5199 /* The instruction itself. */
5200 rtx insn;
5201
5202 /* The initial counter value. This is known to be a general register. */
5203 rtx counter;
5204 };
5205
5206 /* A structure describing a doloop_end. */
5207 struct mep_doloop_end {
5208 /* The next doloop_end with the same loop tag. */
5209 struct mep_doloop_end *next;
5210
5211 /* The instruction itself. */
5212 rtx insn;
5213
5214 /* The first instruction after INSN when the branch isn't taken. */
5215 rtx fallthrough;
5216
5217 /* The location of the counter value. Since doloop_end_internal is a
5218 jump instruction, it has to allow the counter to be stored anywhere
5219 (any non-fixed register or memory location). */
5220 rtx counter;
5221
5222 /* The target label (the place where the insn branches when the counter
5223 isn't zero). */
5224 rtx label;
5225
5226 /* A scratch register. Only available when COUNTER isn't stored
5227 in a general register. */
5228 rtx scratch;
5229 };
5230
5231
5232 /* One do-while loop. */
5233 struct mep_doloop {
5234 /* All the doloop_begins for this loop (in no particular order). */
5235 struct mep_doloop_begin *begin;
5236
5237 /* All the doloop_ends. When there is more than one, arrange things
5238 so that the first one is the most likely to be X in case (2) above. */
5239 struct mep_doloop_end *end;
5240 };
5241
5242
5243 /* Return true if LOOP can be converted into repeat/repeat_end form
5244 (that is, if it matches cases (1) or (2) above). */
5245
5246 static bool
5247 mep_repeat_loop_p (struct mep_doloop *loop)
5248 {
5249 struct mep_doloop_end *end;
5250 rtx fallthrough;
5251
5252 /* There must be exactly one doloop_begin and at least one doloop_end. */
5253 if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0)
5254 return false;
5255
5256 /* The first doloop_end (X) must branch back to the insn after
5257 the doloop_begin. */
5258 if (prev_real_insn (loop->end->label) != loop->begin->insn)
5259 return false;
5260
5261 /* All the other doloop_ends must branch to the same place as X.
5262 When the branch isn't taken, they must jump to the instruction
5263 after X. */
5264 fallthrough = loop->end->fallthrough;
5265 for (end = loop->end->next; end != 0; end = end->next)
5266 if (end->label != loop->end->label
5267 || !simplejump_p (end->fallthrough)
5268 || next_real_insn (JUMP_LABEL (end->fallthrough)) != fallthrough)
5269 return false;
5270
5271 return true;
5272 }
5273
5274
5275 /* The main repeat reorg function. See comment above for details. */
5276
5277 static void
5278 mep_reorg_repeat (rtx insns)
5279 {
5280 rtx insn;
5281 struct mep_doloop *loops, *loop;
5282 struct mep_doloop_begin *begin;
5283 struct mep_doloop_end *end;
5284
5285 /* Quick exit if we haven't created any loops. */
5286 if (cfun->machine->doloop_tags == 0)
5287 return;
5288
5289 /* Create an array of mep_doloop structures. */
5290 loops = (struct mep_doloop *) alloca (sizeof (loops[0]) * cfun->machine->doloop_tags);
5291 memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags);
5292
5293 /* Search the function for do-while insns and group them by loop tag. */
5294 for (insn = insns; insn; insn = NEXT_INSN (insn))
5295 if (INSN_P (insn))
5296 switch (recog_memoized (insn))
5297 {
5298 case CODE_FOR_doloop_begin_internal:
5299 insn_extract (insn);
5300 loop = &loops[INTVAL (recog_data.operand[2])];
5301
5302 begin = (struct mep_doloop_begin *) alloca (sizeof (struct mep_doloop_begin));
5303 begin->next = loop->begin;
5304 begin->insn = insn;
5305 begin->counter = recog_data.operand[0];
5306
5307 loop->begin = begin;
5308 break;
5309
5310 case CODE_FOR_doloop_end_internal:
5311 insn_extract (insn);
5312 loop = &loops[INTVAL (recog_data.operand[2])];
5313
5314 end = (struct mep_doloop_end *) alloca (sizeof (struct mep_doloop_end));
5315 end->insn = insn;
5316 end->fallthrough = next_real_insn (insn);
5317 end->counter = recog_data.operand[0];
5318 end->label = recog_data.operand[1];
5319 end->scratch = recog_data.operand[3];
5320
5321 /* If this insn falls through to an unconditional jump,
5322 give it a lower priority than the others. */
5323 if (loop->end != 0 && simplejump_p (end->fallthrough))
5324 {
5325 end->next = loop->end->next;
5326 loop->end->next = end;
5327 }
5328 else
5329 {
5330 end->next = loop->end;
5331 loop->end = end;
5332 }
5333 break;
5334 }
5335
5336 /* Convert the insns for each loop in turn. */
5337 for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++)
5338 if (mep_repeat_loop_p (loop))
5339 {
5340 /* Case (1) or (2). */
5341 rtx repeat_label, label_ref;
5342
5343 /* Create a new label for the repeat insn. */
5344 repeat_label = gen_label_rtx ();
5345
5346 /* Replace the doloop_begin with a repeat. */
5347 label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label);
5348 emit_insn_before (gen_repeat (loop->begin->counter, label_ref),
5349 loop->begin->insn);
5350 delete_insn (loop->begin->insn);
5351
5352 /* Insert the repeat label before the first doloop_end.
5353 Fill the gap with nops if there are other doloop_ends. */
5354 mep_insert_repeat_label_last (loop->end->insn, repeat_label,
5355 false, loop->end->next != 0);
5356
5357 /* Emit a repeat_end (to improve the readability of the output). */
5358 emit_insn_before (gen_repeat_end (), loop->end->insn);
5359
5360 /* Delete the first doloop_end. */
5361 delete_insn (loop->end->insn);
5362
5363 /* Replace the others with branches to REPEAT_LABEL. */
5364 for (end = loop->end->next; end != 0; end = end->next)
5365 {
5366 emit_jump_insn_before (gen_jump (repeat_label), end->insn);
5367 delete_insn (end->insn);
5368 delete_insn (end->fallthrough);
5369 }
5370 }
5371 else
5372 {
5373 /* Case (3). First replace all the doloop_begins with increment
5374 instructions. */
5375 for (begin = loop->begin; begin != 0; begin = begin->next)
5376 {
5377 emit_insn_before (gen_add3_insn (copy_rtx (begin->counter),
5378 begin->counter, const1_rtx),
5379 begin->insn);
5380 delete_insn (begin->insn);
5381 }
5382
5383 /* Replace all the doloop_ends with decrement-and-branch sequences. */
5384 for (end = loop->end; end != 0; end = end->next)
5385 {
5386 rtx reg;
5387
5388 start_sequence ();
5389
5390 /* Load the counter value into a general register. */
5391 reg = end->counter;
5392 if (!REG_P (reg) || REGNO (reg) > 15)
5393 {
5394 reg = end->scratch;
5395 emit_move_insn (copy_rtx (reg), copy_rtx (end->counter));
5396 }
5397
5398 /* Decrement the counter. */
5399 emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg),
5400 constm1_rtx));
5401
5402 /* Copy it back to its original location. */
5403 if (reg != end->counter)
5404 emit_move_insn (copy_rtx (end->counter), copy_rtx (reg));
5405
5406 /* Jump back to the start label. */
5407 insn = emit_jump_insn (gen_mep_bne_true (reg, const0_rtx,
5408 end->label));
5409 JUMP_LABEL (insn) = end->label;
5410 LABEL_NUSES (end->label)++;
5411
5412 /* Emit the whole sequence before the doloop_end. */
5413 insn = get_insns ();
5414 end_sequence ();
5415 emit_insn_before (insn, end->insn);
5416
5417 /* Delete the doloop_end. */
5418 delete_insn (end->insn);
5419 }
5420 }
5421 }
5422
5423
5424 static bool
5425 mep_invertable_branch_p (rtx insn)
5426 {
5427 rtx cond, set;
5428 enum rtx_code old_code;
5429 int i;
5430
5431 set = PATTERN (insn);
5432 if (GET_CODE (set) != SET)
5433 return false;
5434 if (GET_CODE (XEXP (set, 1)) != IF_THEN_ELSE)
5435 return false;
5436 cond = XEXP (XEXP (set, 1), 0);
5437 old_code = GET_CODE (cond);
5438 switch (old_code)
5439 {
5440 case EQ:
5441 PUT_CODE (cond, NE);
5442 break;
5443 case NE:
5444 PUT_CODE (cond, EQ);
5445 break;
5446 case LT:
5447 PUT_CODE (cond, GE);
5448 break;
5449 case GE:
5450 PUT_CODE (cond, LT);
5451 break;
5452 default:
5453 return false;
5454 }
5455 INSN_CODE (insn) = -1;
5456 i = recog_memoized (insn);
5457 PUT_CODE (cond, old_code);
5458 INSN_CODE (insn) = -1;
5459 return i >= 0;
5460 }
5461
5462 static void
5463 mep_invert_branch (rtx insn, rtx after)
5464 {
5465 rtx cond, set, label;
5466 int i;
5467
5468 set = PATTERN (insn);
5469
5470 gcc_assert (GET_CODE (set) == SET);
5471 gcc_assert (GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE);
5472
5473 cond = XEXP (XEXP (set, 1), 0);
5474 switch (GET_CODE (cond))
5475 {
5476 case EQ:
5477 PUT_CODE (cond, NE);
5478 break;
5479 case NE:
5480 PUT_CODE (cond, EQ);
5481 break;
5482 case LT:
5483 PUT_CODE (cond, GE);
5484 break;
5485 case GE:
5486 PUT_CODE (cond, LT);
5487 break;
5488 default:
5489 gcc_unreachable ();
5490 }
5491 label = gen_label_rtx ();
5492 emit_label_after (label, after);
5493 for (i=1; i<=2; i++)
5494 if (GET_CODE (XEXP (XEXP (set, 1), i)) == LABEL_REF)
5495 {
5496 rtx ref = XEXP (XEXP (set, 1), i);
5497 if (LABEL_NUSES (XEXP (ref, 0)) == 1)
5498 delete_insn (XEXP (ref, 0));
5499 XEXP (ref, 0) = label;
5500 LABEL_NUSES (label) ++;
5501 JUMP_LABEL (insn) = label;
5502 }
5503 INSN_CODE (insn) = -1;
5504 i = recog_memoized (insn);
5505 gcc_assert (i >= 0);
5506 }
5507
5508 static void
5509 mep_reorg_erepeat (rtx insns)
5510 {
5511 rtx insn, prev, l, x;
5512 int count;
5513
5514 for (insn = insns; insn; insn = NEXT_INSN (insn))
5515 if (JUMP_P (insn)
5516 && ! JUMP_TABLE_DATA_P (insn)
5517 && mep_invertable_branch_p (insn))
5518 {
5519 if (dump_file)
5520 {
5521 fprintf (dump_file, "\n------------------------------\n");
5522 fprintf (dump_file, "erepeat: considering this jump:\n");
5523 print_rtl_single (dump_file, insn);
5524 }
5525 count = simplejump_p (insn) ? 0 : 1;
5526 for (prev = PREV_INSN (insn); prev; prev = PREV_INSN (prev))
5527 {
5528 if (GET_CODE (prev) == CALL_INSN
5529 || BARRIER_P (prev))
5530 break;
5531
5532 if (prev == JUMP_LABEL (insn))
5533 {
5534 rtx newlast;
5535 if (dump_file)
5536 fprintf (dump_file, "found loop top, %d insns\n", count);
5537
5538 if (LABEL_NUSES (prev) == 1)
5539 /* We're the only user, always safe */ ;
5540 else if (LABEL_NUSES (prev) == 2)
5541 {
5542 /* See if there's a barrier before this label. If
5543 so, we know nobody inside the loop uses it.
5544 But we must be careful to put the erepeat
5545 *after* the label. */
5546 rtx barrier;
5547 for (barrier = PREV_INSN (prev);
5548 barrier && GET_CODE (barrier) == NOTE;
5549 barrier = PREV_INSN (barrier))
5550 ;
5551 if (barrier && GET_CODE (barrier) != BARRIER)
5552 break;
5553 }
5554 else
5555 {
5556 /* We don't know who else, within or without our loop, uses this */
5557 if (dump_file)
5558 fprintf (dump_file, "... but there are multiple users, too risky.\n");
5559 break;
5560 }
5561
5562 /* Generate a label to be used by the erepat insn. */
5563 l = gen_label_rtx ();
5564
5565 /* Insert the erepeat after INSN's target label. */
5566 x = gen_erepeat (gen_rtx_LABEL_REF (VOIDmode, l));
5567 LABEL_NUSES (l)++;
5568 emit_insn_after (x, prev);
5569
5570 /* Insert the erepeat label. */
5571 newlast = (mep_insert_repeat_label_last
5572 (insn, l, !simplejump_p (insn), false));
5573 if (simplejump_p (insn))
5574 {
5575 emit_insn_before (gen_erepeat_end (), insn);
5576 delete_insn (insn);
5577 }
5578 else
5579 {
5580 mep_invert_branch (insn, newlast);
5581 emit_insn_after (gen_erepeat_end (), newlast);
5582 }
5583 break;
5584 }
5585
5586 if (LABEL_P (prev))
5587 {
5588 /* A label is OK if there is exactly one user, and we
5589 can find that user before the next label. */
5590 rtx user = 0;
5591 int safe = 0;
5592 if (LABEL_NUSES (prev) == 1)
5593 {
5594 for (user = PREV_INSN (prev);
5595 user && (INSN_P (user) || GET_CODE (user) == NOTE);
5596 user = PREV_INSN (user))
5597 if (GET_CODE (user) == JUMP_INSN
5598 && JUMP_LABEL (user) == prev)
5599 {
5600 safe = INSN_UID (user);
5601 break;
5602 }
5603 }
5604 if (!safe)
5605 break;
5606 if (dump_file)
5607 fprintf (dump_file, "... ignoring jump from insn %d to %d\n",
5608 safe, INSN_UID (prev));
5609 }
5610
5611 if (INSN_P (prev))
5612 {
5613 count ++;
5614 }
5615 }
5616 }
5617 if (dump_file)
5618 fprintf (dump_file, "\n==============================\n");
5619 }
5620
5621 /* Replace a jump to a return, with a copy of the return. GCC doesn't
5622 always do this on its own. */
5623
5624 static void
5625 mep_jmp_return_reorg (rtx insns)
5626 {
5627 rtx insn, label, ret;
5628 int ret_code;
5629
5630 for (insn = insns; insn; insn = NEXT_INSN (insn))
5631 if (simplejump_p (insn))
5632 {
5633 /* Find the fist real insn the jump jumps to. */
5634 label = ret = JUMP_LABEL (insn);
5635 while (ret
5636 && (GET_CODE (ret) == NOTE
5637 || GET_CODE (ret) == CODE_LABEL
5638 || GET_CODE (PATTERN (ret)) == USE))
5639 ret = NEXT_INSN (ret);
5640
5641 if (ret)
5642 {
5643 /* Is it a return? */
5644 ret_code = recog_memoized (ret);
5645 if (ret_code == CODE_FOR_return_internal
5646 || ret_code == CODE_FOR_eh_return_internal)
5647 {
5648 /* It is. Replace the jump with a return. */
5649 LABEL_NUSES (label) --;
5650 if (LABEL_NUSES (label) == 0)
5651 delete_insn (label);
5652 PATTERN (insn) = copy_rtx (PATTERN (ret));
5653 INSN_CODE (insn) = -1;
5654 }
5655 }
5656 }
5657 }
5658
5659
5660 static void
5661 mep_reorg_addcombine (rtx insns)
5662 {
5663 rtx i, n;
5664
5665 for (i = insns; i; i = NEXT_INSN (i))
5666 if (INSN_P (i)
5667 && INSN_CODE (i) == CODE_FOR_addsi3
5668 && GET_CODE (SET_DEST (PATTERN (i))) == REG
5669 && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 0)) == REG
5670 && REGNO (SET_DEST (PATTERN (i))) == REGNO (XEXP (SET_SRC (PATTERN (i)), 0))
5671 && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 1)) == CONST_INT)
5672 {
5673 n = NEXT_INSN (i);
5674 if (INSN_P (n)
5675 && INSN_CODE (n) == CODE_FOR_addsi3
5676 && GET_CODE (SET_DEST (PATTERN (n))) == REG
5677 && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 0)) == REG
5678 && REGNO (SET_DEST (PATTERN (n))) == REGNO (XEXP (SET_SRC (PATTERN (n)), 0))
5679 && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 1)) == CONST_INT)
5680 {
5681 int ic = INTVAL (XEXP (SET_SRC (PATTERN (i)), 1));
5682 int nc = INTVAL (XEXP (SET_SRC (PATTERN (n)), 1));
5683 if (REGNO (SET_DEST (PATTERN (i))) == REGNO (SET_DEST (PATTERN (n)))
5684 && ic + nc < 32767
5685 && ic + nc > -32768)
5686 {
5687 XEXP (SET_SRC (PATTERN (i)), 1) = GEN_INT (ic + nc);
5688 NEXT_INSN (i) = NEXT_INSN (n);
5689 if (NEXT_INSN (i))
5690 PREV_INSN (NEXT_INSN (i)) = i;
5691 }
5692 }
5693 }
5694 }
5695
5696 /* If this insn adjusts the stack, return the adjustment, else return
5697 zero. */
5698 static int
5699 add_sp_insn_p (rtx insn)
5700 {
5701 rtx pat;
5702
5703 if (! single_set (insn))
5704 return 0;
5705 pat = PATTERN (insn);
5706 if (GET_CODE (SET_DEST (pat)) != REG)
5707 return 0;
5708 if (REGNO (SET_DEST (pat)) != SP_REGNO)
5709 return 0;
5710 if (GET_CODE (SET_SRC (pat)) != PLUS)
5711 return 0;
5712 if (GET_CODE (XEXP (SET_SRC (pat), 0)) != REG)
5713 return 0;
5714 if (REGNO (XEXP (SET_SRC (pat), 0)) != SP_REGNO)
5715 return 0;
5716 if (GET_CODE (XEXP (SET_SRC (pat), 1)) != CONST_INT)
5717 return 0;
5718 return INTVAL (XEXP (SET_SRC (pat), 1));
5719 }
5720
5721 /* Check for trivial functions that set up an unneeded stack
5722 frame. */
5723 static void
5724 mep_reorg_noframe (rtx insns)
5725 {
5726 rtx start_frame_insn;
5727 rtx end_frame_insn = 0;
5728 int sp_adjust, sp2;
5729 rtx sp;
5730
5731 /* The first insn should be $sp = $sp + N */
5732 while (insns && ! INSN_P (insns))
5733 insns = NEXT_INSN (insns);
5734 if (!insns)
5735 return;
5736
5737 sp_adjust = add_sp_insn_p (insns);
5738 if (sp_adjust == 0)
5739 return;
5740
5741 start_frame_insn = insns;
5742 sp = SET_DEST (PATTERN (start_frame_insn));
5743
5744 insns = next_real_insn (insns);
5745
5746 while (insns)
5747 {
5748 rtx next = next_real_insn (insns);
5749 if (!next)
5750 break;
5751
5752 sp2 = add_sp_insn_p (insns);
5753 if (sp2)
5754 {
5755 if (end_frame_insn)
5756 return;
5757 end_frame_insn = insns;
5758 if (sp2 != -sp_adjust)
5759 return;
5760 }
5761 else if (mep_mentioned_p (insns, sp, 0))
5762 return;
5763 else if (CALL_P (insns))
5764 return;
5765
5766 insns = next;
5767 }
5768
5769 if (end_frame_insn)
5770 {
5771 delete_insn (start_frame_insn);
5772 delete_insn (end_frame_insn);
5773 }
5774 }
5775
5776 static void
5777 mep_reorg (void)
5778 {
5779 rtx insns = get_insns ();
5780
5781 /* We require accurate REG_DEAD notes. */
5782 compute_bb_for_insn ();
5783 df_note_add_problem ();
5784 df_analyze ();
5785
5786 mep_reorg_addcombine (insns);
5787 #if EXPERIMENTAL_REGMOVE_REORG
5788 /* VLIW packing has been done already, so we can't just delete things. */
5789 if (!mep_vliw_function_p (cfun->decl))
5790 mep_reorg_regmove (insns);
5791 #endif
5792 mep_jmp_return_reorg (insns);
5793 mep_bundle_insns (insns);
5794 mep_reorg_repeat (insns);
5795 if (optimize
5796 && !profile_flag
5797 && !profile_arc_flag
5798 && TARGET_OPT_REPEAT
5799 && (!mep_interrupt_p () || mep_interrupt_saved_reg (RPB_REGNO)))
5800 mep_reorg_erepeat (insns);
5801
5802 /* This may delete *insns so make sure it's last. */
5803 mep_reorg_noframe (insns);
5804
5805 df_finish_pass (false);
5806 }
5807
5808 \f
5809
5810 /*----------------------------------------------------------------------*/
5811 /* Builtins */
5812 /*----------------------------------------------------------------------*/
5813
5814 /* Element X gives the index into cgen_insns[] of the most general
5815 implementation of intrinsic X. Unimplemented intrinsics are
5816 mapped to -1. */
5817 int mep_intrinsic_insn[ARRAY_SIZE (cgen_intrinsics)];
5818
5819 /* Element X gives the index of another instruction that is mapped to
5820 the same intrinsic as cgen_insns[X]. It is -1 when there is no other
5821 instruction.
5822
5823 Things are set up so that mep_intrinsic_chain[X] < X. */
5824 static int mep_intrinsic_chain[ARRAY_SIZE (cgen_insns)];
5825
5826 /* The bitmask for the current ISA. The ISA masks are declared
5827 in mep-intrin.h. */
5828 unsigned int mep_selected_isa;
5829
5830 struct mep_config {
5831 const char *config_name;
5832 unsigned int isa;
5833 };
5834
5835 static struct mep_config mep_configs[] = {
5836 #ifdef COPROC_SELECTION_TABLE
5837 COPROC_SELECTION_TABLE,
5838 #endif
5839 { 0, 0 }
5840 };
5841
5842 /* Initialize the global intrinsics variables above. */
5843
5844 static void
5845 mep_init_intrinsics (void)
5846 {
5847 size_t i;
5848
5849 /* Set MEP_SELECTED_ISA to the ISA flag for this configuration. */
5850 mep_selected_isa = mep_configs[0].isa;
5851 if (mep_config_string != 0)
5852 for (i = 0; mep_configs[i].config_name; i++)
5853 if (strcmp (mep_config_string, mep_configs[i].config_name) == 0)
5854 {
5855 mep_selected_isa = mep_configs[i].isa;
5856 break;
5857 }
5858
5859 /* Assume all intrinsics are unavailable. */
5860 for (i = 0; i < ARRAY_SIZE (mep_intrinsic_insn); i++)
5861 mep_intrinsic_insn[i] = -1;
5862
5863 /* Build up the global intrinsic tables. */
5864 for (i = 0; i < ARRAY_SIZE (cgen_insns); i++)
5865 if ((cgen_insns[i].isas & mep_selected_isa) != 0)
5866 {
5867 mep_intrinsic_chain[i] = mep_intrinsic_insn[cgen_insns[i].intrinsic];
5868 mep_intrinsic_insn[cgen_insns[i].intrinsic] = i;
5869 }
5870 /* See whether we can directly move values between one coprocessor
5871 register and another. */
5872 for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++)
5873 if (MEP_INTRINSIC_AVAILABLE_P (mep_cmov_insns[i]))
5874 mep_have_copro_copro_moves_p = true;
5875
5876 /* See whether we can directly move values between core and
5877 coprocessor registers. */
5878 mep_have_core_copro_moves_p = (MEP_INTRINSIC_AVAILABLE_P (mep_cmov1)
5879 && MEP_INTRINSIC_AVAILABLE_P (mep_cmov2));
5880
5881 mep_have_core_copro_moves_p = 1;
5882 }
5883
5884 /* Declare all available intrinsic functions. Called once only. */
5885
5886 static tree cp_data_bus_int_type_node;
5887 static tree opaque_vector_type_node;
5888 static tree v8qi_type_node;
5889 static tree v4hi_type_node;
5890 static tree v2si_type_node;
5891 static tree v8uqi_type_node;
5892 static tree v4uhi_type_node;
5893 static tree v2usi_type_node;
5894
5895 static tree
5896 mep_cgen_regnum_to_type (enum cgen_regnum_operand_type cr)
5897 {
5898 switch (cr)
5899 {
5900 case cgen_regnum_operand_type_POINTER: return ptr_type_node;
5901 case cgen_regnum_operand_type_LONG: return long_integer_type_node;
5902 case cgen_regnum_operand_type_ULONG: return long_unsigned_type_node;
5903 case cgen_regnum_operand_type_SHORT: return short_integer_type_node;
5904 case cgen_regnum_operand_type_USHORT: return short_unsigned_type_node;
5905 case cgen_regnum_operand_type_CHAR: return char_type_node;
5906 case cgen_regnum_operand_type_UCHAR: return unsigned_char_type_node;
5907 case cgen_regnum_operand_type_SI: return intSI_type_node;
5908 case cgen_regnum_operand_type_DI: return intDI_type_node;
5909 case cgen_regnum_operand_type_VECTOR: return opaque_vector_type_node;
5910 case cgen_regnum_operand_type_V8QI: return v8qi_type_node;
5911 case cgen_regnum_operand_type_V4HI: return v4hi_type_node;
5912 case cgen_regnum_operand_type_V2SI: return v2si_type_node;
5913 case cgen_regnum_operand_type_V8UQI: return v8uqi_type_node;
5914 case cgen_regnum_operand_type_V4UHI: return v4uhi_type_node;
5915 case cgen_regnum_operand_type_V2USI: return v2usi_type_node;
5916 case cgen_regnum_operand_type_CP_DATA_BUS_INT: return cp_data_bus_int_type_node;
5917 default:
5918 return void_type_node;
5919 }
5920 }
5921
5922 static void
5923 mep_init_builtins (void)
5924 {
5925 size_t i;
5926
5927 if (TARGET_64BIT_CR_REGS)
5928 cp_data_bus_int_type_node = long_long_integer_type_node;
5929 else
5930 cp_data_bus_int_type_node = long_integer_type_node;
5931
5932 opaque_vector_type_node = build_opaque_vector_type (intQI_type_node, 8);
5933 v8qi_type_node = build_vector_type (intQI_type_node, 8);
5934 v4hi_type_node = build_vector_type (intHI_type_node, 4);
5935 v2si_type_node = build_vector_type (intSI_type_node, 2);
5936 v8uqi_type_node = build_vector_type (unsigned_intQI_type_node, 8);
5937 v4uhi_type_node = build_vector_type (unsigned_intHI_type_node, 4);
5938 v2usi_type_node = build_vector_type (unsigned_intSI_type_node, 2);
5939
5940 add_builtin_type ("cp_data_bus_int", cp_data_bus_int_type_node);
5941
5942 add_builtin_type ("cp_vector", opaque_vector_type_node);
5943
5944 add_builtin_type ("cp_v8qi", v8qi_type_node);
5945 add_builtin_type ("cp_v4hi", v4hi_type_node);
5946 add_builtin_type ("cp_v2si", v2si_type_node);
5947
5948 add_builtin_type ("cp_v8uqi", v8uqi_type_node);
5949 add_builtin_type ("cp_v4uhi", v4uhi_type_node);
5950 add_builtin_type ("cp_v2usi", v2usi_type_node);
5951
5952 /* Intrinsics like mep_cadd3 are implemented with two groups of
5953 instructions, one which uses UNSPECs and one which uses a specific
5954 rtl code such as PLUS. Instructions in the latter group belong
5955 to GROUP_KNOWN_CODE.
5956
5957 In such cases, the intrinsic will have two entries in the global
5958 tables above. The unspec form is accessed using builtin functions
5959 while the specific form is accessed using the mep_* enum in
5960 mep-intrin.h.
5961
5962 The idea is that __cop arithmetic and builtin functions have
5963 different optimization requirements. If mep_cadd3() appears in
5964 the source code, the user will surely except gcc to use cadd3
5965 rather than a work-alike such as add3. However, if the user
5966 just writes "a + b", where a or b are __cop variables, it is
5967 reasonable for gcc to choose a core instruction rather than
5968 cadd3 if it believes that is more optimal. */
5969 for (i = 0; i < ARRAY_SIZE (cgen_insns); i++)
5970 if ((cgen_insns[i].groups & GROUP_KNOWN_CODE) == 0
5971 && mep_intrinsic_insn[cgen_insns[i].intrinsic] >= 0)
5972 {
5973 tree ret_type = void_type_node;
5974 tree bi_type;
5975
5976 if (i > 0 && cgen_insns[i].intrinsic == cgen_insns[i-1].intrinsic)
5977 continue;
5978
5979 if (cgen_insns[i].cret_p)
5980 ret_type = mep_cgen_regnum_to_type (cgen_insns[i].regnums[0].type);
5981
5982 bi_type = build_function_type_list (ret_type, NULL_TREE);
5983 add_builtin_function (cgen_intrinsics[cgen_insns[i].intrinsic],
5984 bi_type,
5985 cgen_insns[i].intrinsic, BUILT_IN_MD, NULL, NULL);
5986 }
5987 }
5988
5989 /* Report the unavailablity of the given intrinsic. */
5990
5991 #if 1
5992 static void
5993 mep_intrinsic_unavailable (int intrinsic)
5994 {
5995 static int already_reported_p[ARRAY_SIZE (cgen_intrinsics)];
5996
5997 if (already_reported_p[intrinsic])
5998 return;
5999
6000 if (mep_intrinsic_insn[intrinsic] < 0)
6001 error ("coprocessor intrinsic %qs is not available in this configuration",
6002 cgen_intrinsics[intrinsic]);
6003 else if (CGEN_CURRENT_GROUP == GROUP_VLIW)
6004 error ("%qs is not available in VLIW functions",
6005 cgen_intrinsics[intrinsic]);
6006 else
6007 error ("%qs is not available in non-VLIW functions",
6008 cgen_intrinsics[intrinsic]);
6009
6010 already_reported_p[intrinsic] = 1;
6011 }
6012 #endif
6013
6014
6015 /* See if any implementation of INTRINSIC is available to the
6016 current function. If so, store the most general implementation
6017 in *INSN_PTR and return true. Return false otherwise. */
6018
6019 static bool
6020 mep_get_intrinsic_insn (int intrinsic ATTRIBUTE_UNUSED, const struct cgen_insn **insn_ptr ATTRIBUTE_UNUSED)
6021 {
6022 int i;
6023
6024 i = mep_intrinsic_insn[intrinsic];
6025 while (i >= 0 && !CGEN_ENABLE_INSN_P (i))
6026 i = mep_intrinsic_chain[i];
6027
6028 if (i >= 0)
6029 {
6030 *insn_ptr = &cgen_insns[i];
6031 return true;
6032 }
6033 return false;
6034 }
6035
6036
6037 /* Like mep_get_intrinsic_insn, but with extra handling for moves.
6038 If INTRINSIC is mep_cmov, but there is no pure CR <- CR move insn,
6039 try using a work-alike instead. In this case, the returned insn
6040 may have three operands rather than two. */
6041
6042 static bool
6043 mep_get_move_insn (int intrinsic, const struct cgen_insn **cgen_insn)
6044 {
6045 size_t i;
6046
6047 if (intrinsic == mep_cmov)
6048 {
6049 for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++)
6050 if (mep_get_intrinsic_insn (mep_cmov_insns[i], cgen_insn))
6051 return true;
6052 return false;
6053 }
6054 return mep_get_intrinsic_insn (intrinsic, cgen_insn);
6055 }
6056
6057
6058 /* If ARG is a register operand that is the same size as MODE, convert it
6059 to MODE using a subreg. Otherwise return ARG as-is. */
6060
6061 static rtx
6062 mep_convert_arg (enum machine_mode mode, rtx arg)
6063 {
6064 if (GET_MODE (arg) != mode
6065 && register_operand (arg, VOIDmode)
6066 && GET_MODE_SIZE (GET_MODE (arg)) == GET_MODE_SIZE (mode))
6067 return simplify_gen_subreg (mode, arg, GET_MODE (arg), 0);
6068 return arg;
6069 }
6070
6071
6072 /* Apply regnum conversions to ARG using the description given by REGNUM.
6073 Return the new argument on success and null on failure. */
6074
6075 static rtx
6076 mep_convert_regnum (const struct cgen_regnum_operand *regnum, rtx arg)
6077 {
6078 if (regnum->count == 0)
6079 return arg;
6080
6081 if (GET_CODE (arg) != CONST_INT
6082 || INTVAL (arg) < 0
6083 || INTVAL (arg) >= regnum->count)
6084 return 0;
6085
6086 return gen_rtx_REG (SImode, INTVAL (arg) + regnum->base);
6087 }
6088
6089
6090 /* Try to make intrinsic argument ARG match the given operand.
6091 UNSIGNED_P is true if the argument has an unsigned type. */
6092
6093 static rtx
6094 mep_legitimize_arg (const struct insn_operand_data *operand, rtx arg,
6095 int unsigned_p)
6096 {
6097 if (GET_CODE (arg) == CONST_INT)
6098 {
6099 /* CONST_INTs can only be bound to integer operands. */
6100 if (GET_MODE_CLASS (operand->mode) != MODE_INT)
6101 return 0;
6102 }
6103 else if (GET_CODE (arg) == CONST_DOUBLE)
6104 /* These hold vector constants. */;
6105 else if (GET_MODE_SIZE (GET_MODE (arg)) != GET_MODE_SIZE (operand->mode))
6106 {
6107 /* If the argument is a different size from what's expected, we must
6108 have a value in the right mode class in order to convert it. */
6109 if (GET_MODE_CLASS (operand->mode) != GET_MODE_CLASS (GET_MODE (arg)))
6110 return 0;
6111
6112 /* If the operand is an rvalue, promote or demote it to match the
6113 operand's size. This might not need extra instructions when
6114 ARG is a register value. */
6115 if (operand->constraint[0] != '=')
6116 arg = convert_to_mode (operand->mode, arg, unsigned_p);
6117 }
6118
6119 /* If the operand is an lvalue, bind the operand to a new register.
6120 The caller will copy this value into ARG after the main
6121 instruction. By doing this always, we produce slightly more
6122 optimal code. */
6123 /* But not for control registers. */
6124 if (operand->constraint[0] == '='
6125 && (! REG_P (arg)
6126 || ! (CONTROL_REGNO_P (REGNO (arg))
6127 || CCR_REGNO_P (REGNO (arg))
6128 || CR_REGNO_P (REGNO (arg)))
6129 ))
6130 return gen_reg_rtx (operand->mode);
6131
6132 /* Try simple mode punning. */
6133 arg = mep_convert_arg (operand->mode, arg);
6134 if (operand->predicate (arg, operand->mode))
6135 return arg;
6136
6137 /* See if forcing the argument into a register will make it match. */
6138 if (GET_CODE (arg) == CONST_INT || GET_CODE (arg) == CONST_DOUBLE)
6139 arg = force_reg (operand->mode, arg);
6140 else
6141 arg = mep_convert_arg (operand->mode, force_reg (GET_MODE (arg), arg));
6142 if (operand->predicate (arg, operand->mode))
6143 return arg;
6144
6145 return 0;
6146 }
6147
6148
6149 /* Report that ARG cannot be passed to argument ARGNUM of intrinsic
6150 function FNNAME. OPERAND describes the operand to which ARGNUM
6151 is mapped. */
6152
6153 static void
6154 mep_incompatible_arg (const struct insn_operand_data *operand, rtx arg,
6155 int argnum, tree fnname)
6156 {
6157 size_t i;
6158
6159 if (GET_CODE (arg) == CONST_INT)
6160 for (i = 0; i < ARRAY_SIZE (cgen_immediate_predicates); i++)
6161 if (operand->predicate == cgen_immediate_predicates[i].predicate)
6162 {
6163 const struct cgen_immediate_predicate *predicate;
6164 HOST_WIDE_INT argval;
6165
6166 predicate = &cgen_immediate_predicates[i];
6167 argval = INTVAL (arg);
6168 if (argval < predicate->lower || argval >= predicate->upper)
6169 error ("argument %d of %qE must be in the range %d...%d",
6170 argnum, fnname, predicate->lower, predicate->upper - 1);
6171 else
6172 error ("argument %d of %qE must be a multiple of %d",
6173 argnum, fnname, predicate->align);
6174 return;
6175 }
6176
6177 error ("incompatible type for argument %d of %qE", argnum, fnname);
6178 }
6179
6180 static rtx
6181 mep_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6182 rtx subtarget ATTRIBUTE_UNUSED,
6183 enum machine_mode mode ATTRIBUTE_UNUSED,
6184 int ignore ATTRIBUTE_UNUSED)
6185 {
6186 rtx pat, op[10], arg[10];
6187 unsigned int a;
6188 int opindex, unsigned_p[10];
6189 tree fndecl, args;
6190 unsigned int n_args;
6191 tree fnname;
6192 const struct cgen_insn *cgen_insn;
6193 const struct insn_data_d *idata;
6194 unsigned int first_arg = 0;
6195 unsigned int builtin_n_args;
6196
6197 fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6198 fnname = DECL_NAME (fndecl);
6199
6200 /* Find out which instruction we should emit. Note that some coprocessor
6201 intrinsics may only be available in VLIW mode, or only in normal mode. */
6202 if (!mep_get_intrinsic_insn (DECL_FUNCTION_CODE (fndecl), &cgen_insn))
6203 {
6204 mep_intrinsic_unavailable (DECL_FUNCTION_CODE (fndecl));
6205 return NULL_RTX;
6206 }
6207 idata = &insn_data[cgen_insn->icode];
6208
6209 builtin_n_args = cgen_insn->num_args;
6210
6211 if (cgen_insn->cret_p)
6212 {
6213 if (cgen_insn->cret_p > 1)
6214 builtin_n_args ++;
6215 first_arg = 1;
6216 mep_cgen_regnum_to_type (cgen_insn->regnums[0].type);
6217 builtin_n_args --;
6218 }
6219
6220 /* Evaluate each argument. */
6221 n_args = call_expr_nargs (exp);
6222
6223 if (n_args < builtin_n_args)
6224 {
6225 error ("too few arguments to %qE", fnname);
6226 return NULL_RTX;
6227 }
6228 if (n_args > builtin_n_args)
6229 {
6230 error ("too many arguments to %qE", fnname);
6231 return NULL_RTX;
6232 }
6233
6234 for (a = first_arg; a < builtin_n_args + first_arg; a++)
6235 {
6236 tree value;
6237
6238 args = CALL_EXPR_ARG (exp, a - first_arg);
6239
6240 value = args;
6241
6242 #if 0
6243 if (cgen_insn->regnums[a].reference_p)
6244 {
6245 if (TREE_CODE (value) != ADDR_EXPR)
6246 {
6247 debug_tree(value);
6248 error ("argument %d of %qE must be an address", a+1, fnname);
6249 return NULL_RTX;
6250 }
6251 value = TREE_OPERAND (value, 0);
6252 }
6253 #endif
6254
6255 /* If the argument has been promoted to int, get the unpromoted
6256 value. This is necessary when sub-int memory values are bound
6257 to reference parameters. */
6258 if (TREE_CODE (value) == NOP_EXPR
6259 && TREE_TYPE (value) == integer_type_node
6260 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
6261 && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))
6262 < TYPE_PRECISION (TREE_TYPE (value))))
6263 value = TREE_OPERAND (value, 0);
6264
6265 /* If the argument has been promoted to double, get the unpromoted
6266 SFmode value. This is necessary for FMAX support, for example. */
6267 if (TREE_CODE (value) == NOP_EXPR
6268 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (value))
6269 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
6270 && TYPE_MODE (TREE_TYPE (value)) == DFmode
6271 && TYPE_MODE (TREE_TYPE (TREE_OPERAND (value, 0))) == SFmode)
6272 value = TREE_OPERAND (value, 0);
6273
6274 unsigned_p[a] = TYPE_UNSIGNED (TREE_TYPE (value));
6275 arg[a] = expand_expr (value, NULL, VOIDmode, EXPAND_NORMAL);
6276 arg[a] = mep_convert_regnum (&cgen_insn->regnums[a], arg[a]);
6277 if (cgen_insn->regnums[a].reference_p)
6278 {
6279 tree pointed_to = TREE_TYPE (TREE_TYPE (value));
6280 enum machine_mode pointed_mode = TYPE_MODE (pointed_to);
6281
6282 arg[a] = gen_rtx_MEM (pointed_mode, arg[a]);
6283 }
6284 if (arg[a] == 0)
6285 {
6286 error ("argument %d of %qE must be in the range %d...%d",
6287 a + 1, fnname, 0, cgen_insn->regnums[a].count - 1);
6288 return NULL_RTX;
6289 }
6290 }
6291
6292 for (a = 0; a < first_arg; a++)
6293 {
6294 if (a == 0 && target && GET_MODE (target) == idata->operand[0].mode)
6295 arg[a] = target;
6296 else
6297 arg[a] = gen_reg_rtx (idata->operand[0].mode);
6298 }
6299
6300 /* Convert the arguments into a form suitable for the intrinsic.
6301 Report an error if this isn't possible. */
6302 for (opindex = 0; opindex < idata->n_operands; opindex++)
6303 {
6304 a = cgen_insn->op_mapping[opindex];
6305 op[opindex] = mep_legitimize_arg (&idata->operand[opindex],
6306 arg[a], unsigned_p[a]);
6307 if (op[opindex] == 0)
6308 {
6309 mep_incompatible_arg (&idata->operand[opindex],
6310 arg[a], a + 1 - first_arg, fnname);
6311 return NULL_RTX;
6312 }
6313 }
6314
6315 /* Emit the instruction. */
6316 pat = idata->genfun (op[0], op[1], op[2], op[3], op[4],
6317 op[5], op[6], op[7], op[8], op[9]);
6318
6319 if (GET_CODE (pat) == SET
6320 && GET_CODE (SET_DEST (pat)) == PC
6321 && GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
6322 emit_jump_insn (pat);
6323 else
6324 emit_insn (pat);
6325
6326 /* Copy lvalues back to their final locations. */
6327 for (opindex = 0; opindex < idata->n_operands; opindex++)
6328 if (idata->operand[opindex].constraint[0] == '=')
6329 {
6330 a = cgen_insn->op_mapping[opindex];
6331 if (a >= first_arg)
6332 {
6333 if (GET_MODE_CLASS (GET_MODE (arg[a]))
6334 != GET_MODE_CLASS (GET_MODE (op[opindex])))
6335 emit_move_insn (arg[a], gen_lowpart (GET_MODE (arg[a]),
6336 op[opindex]));
6337 else
6338 {
6339 /* First convert the operand to the right mode, then copy it
6340 into the destination. Doing the conversion as a separate
6341 step (rather than using convert_move) means that we can
6342 avoid creating no-op moves when ARG[A] and OP[OPINDEX]
6343 refer to the same register. */
6344 op[opindex] = convert_to_mode (GET_MODE (arg[a]),
6345 op[opindex], unsigned_p[a]);
6346 if (!rtx_equal_p (arg[a], op[opindex]))
6347 emit_move_insn (arg[a], op[opindex]);
6348 }
6349 }
6350 }
6351
6352 if (first_arg > 0 && target && target != op[0])
6353 {
6354 emit_move_insn (target, op[0]);
6355 }
6356
6357 return target;
6358 }
6359
6360 static bool
6361 mep_vector_mode_supported_p (enum machine_mode mode ATTRIBUTE_UNUSED)
6362 {
6363 return false;
6364 }
6365 \f
6366 /* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions
6367 a global register. */
6368
6369 static int
6370 global_reg_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6371 {
6372 int regno;
6373 rtx x = *loc;
6374
6375 if (! x)
6376 return 0;
6377
6378 switch (GET_CODE (x))
6379 {
6380 case SUBREG:
6381 if (REG_P (SUBREG_REG (x)))
6382 {
6383 if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
6384 && global_regs[subreg_regno (x)])
6385 return 1;
6386 return 0;
6387 }
6388 break;
6389
6390 case REG:
6391 regno = REGNO (x);
6392 if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
6393 return 1;
6394 return 0;
6395
6396 case SCRATCH:
6397 case PC:
6398 case CC0:
6399 case CONST_INT:
6400 case CONST_DOUBLE:
6401 case CONST:
6402 case LABEL_REF:
6403 return 0;
6404
6405 case CALL:
6406 /* A non-constant call might use a global register. */
6407 return 1;
6408
6409 default:
6410 break;
6411 }
6412
6413 return 0;
6414 }
6415
6416 /* Returns nonzero if X mentions a global register. */
6417
6418 static int
6419 global_reg_mentioned_p (rtx x)
6420 {
6421 if (INSN_P (x))
6422 {
6423 if (CALL_P (x))
6424 {
6425 if (! RTL_CONST_OR_PURE_CALL_P (x))
6426 return 1;
6427 x = CALL_INSN_FUNCTION_USAGE (x);
6428 if (x == 0)
6429 return 0;
6430 }
6431 else
6432 x = PATTERN (x);
6433 }
6434
6435 return for_each_rtx (&x, global_reg_mentioned_p_1, NULL);
6436 }
6437 /* Scheduling hooks for VLIW mode.
6438
6439 Conceptually this is very simple: we have a two-pack architecture
6440 that takes one core insn and one coprocessor insn to make up either
6441 a 32- or 64-bit instruction word (depending on the option bit set in
6442 the chip). I.e. in VL32 mode, we can pack one 16-bit core insn and
6443 one 16-bit cop insn; in VL64 mode we can pack one 16-bit core insn
6444 and one 48-bit cop insn or two 32-bit core/cop insns.
6445
6446 In practice, instruction selection will be a bear. Consider in
6447 VL64 mode the following insns
6448
6449 add $1, 1
6450 cmov $cr0, $0
6451
6452 these cannot pack, since the add is a 16-bit core insn and cmov
6453 is a 32-bit cop insn. However,
6454
6455 add3 $1, $1, 1
6456 cmov $cr0, $0
6457
6458 packs just fine. For good VLIW code generation in VL64 mode, we
6459 will have to have 32-bit alternatives for many of the common core
6460 insns. Not implemented. */
6461
6462 static int
6463 mep_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
6464 {
6465 int cost_specified;
6466
6467 if (REG_NOTE_KIND (link) != 0)
6468 {
6469 /* See whether INSN and DEP_INSN are intrinsics that set the same
6470 hard register. If so, it is more important to free up DEP_INSN
6471 than it is to free up INSN.
6472
6473 Note that intrinsics like mep_mulr are handled differently from
6474 the equivalent mep.md patterns. In mep.md, if we don't care
6475 about the value of $lo and $hi, the pattern will just clobber
6476 the registers, not set them. Since clobbers don't count as
6477 output dependencies, it is often possible to reorder two mulrs,
6478 even after reload.
6479
6480 In contrast, mep_mulr() sets both $lo and $hi to specific values,
6481 so any pair of mep_mulr()s will be inter-dependent. We should
6482 therefore give the first mep_mulr() a higher priority. */
6483 if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT
6484 && global_reg_mentioned_p (PATTERN (insn))
6485 && global_reg_mentioned_p (PATTERN (dep_insn)))
6486 return 1;
6487
6488 /* If the dependence is an anti or output dependence, assume it
6489 has no cost. */
6490 return 0;
6491 }
6492
6493 /* If we can't recognize the insns, we can't really do anything. */
6494 if (recog_memoized (dep_insn) < 0)
6495 return cost;
6496
6497 /* The latency attribute doesn't apply to MeP-h1: we use the stall
6498 attribute instead. */
6499 if (!TARGET_H1)
6500 {
6501 cost_specified = get_attr_latency (dep_insn);
6502 if (cost_specified != 0)
6503 return cost_specified;
6504 }
6505
6506 return cost;
6507 }
6508
6509 /* ??? We don't properly compute the length of a load/store insn,
6510 taking into account the addressing mode. */
6511
6512 static int
6513 mep_issue_rate (void)
6514 {
6515 return TARGET_IVC2 ? 3 : 2;
6516 }
6517
6518 /* Return true if function DECL was declared with the vliw attribute. */
6519
6520 bool
6521 mep_vliw_function_p (tree decl)
6522 {
6523 return lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))) != 0;
6524 }
6525
6526 static rtx
6527 mep_find_ready_insn (rtx *ready, int nready, enum attr_slot slot, int length)
6528 {
6529 int i;
6530
6531 for (i = nready - 1; i >= 0; --i)
6532 {
6533 rtx insn = ready[i];
6534 if (recog_memoized (insn) >= 0
6535 && get_attr_slot (insn) == slot
6536 && get_attr_length (insn) == length)
6537 return insn;
6538 }
6539
6540 return NULL_RTX;
6541 }
6542
6543 static void
6544 mep_move_ready_insn (rtx *ready, int nready, rtx insn)
6545 {
6546 int i;
6547
6548 for (i = 0; i < nready; ++i)
6549 if (ready[i] == insn)
6550 {
6551 for (; i < nready - 1; ++i)
6552 ready[i] = ready[i + 1];
6553 ready[i] = insn;
6554 return;
6555 }
6556
6557 gcc_unreachable ();
6558 }
6559
6560 static void
6561 mep_print_sched_insn (FILE *dump, rtx insn)
6562 {
6563 const char *slots = "none";
6564 const char *name = NULL;
6565 int code;
6566 char buf[30];
6567
6568 if (GET_CODE (PATTERN (insn)) == SET
6569 || GET_CODE (PATTERN (insn)) == PARALLEL)
6570 {
6571 switch (get_attr_slots (insn))
6572 {
6573 case SLOTS_CORE: slots = "core"; break;
6574 case SLOTS_C3: slots = "c3"; break;
6575 case SLOTS_P0: slots = "p0"; break;
6576 case SLOTS_P0_P0S: slots = "p0,p0s"; break;
6577 case SLOTS_P0_P1: slots = "p0,p1"; break;
6578 case SLOTS_P0S: slots = "p0s"; break;
6579 case SLOTS_P0S_P1: slots = "p0s,p1"; break;
6580 case SLOTS_P1: slots = "p1"; break;
6581 default:
6582 sprintf(buf, "%d", get_attr_slots (insn));
6583 slots = buf;
6584 break;
6585 }
6586 }
6587 if (GET_CODE (PATTERN (insn)) == USE)
6588 slots = "use";
6589
6590 code = INSN_CODE (insn);
6591 if (code >= 0)
6592 name = get_insn_name (code);
6593 if (!name)
6594 name = "{unknown}";
6595
6596 fprintf (dump,
6597 "insn %4d %4d %8s %s\n",
6598 code,
6599 INSN_UID (insn),
6600 name,
6601 slots);
6602 }
6603
6604 static int
6605 mep_sched_reorder (FILE *dump ATTRIBUTE_UNUSED,
6606 int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
6607 int *pnready, int clock ATTRIBUTE_UNUSED)
6608 {
6609 int nready = *pnready;
6610 rtx core_insn, cop_insn;
6611 int i;
6612
6613 if (dump && sched_verbose > 1)
6614 {
6615 fprintf (dump, "\nsched_reorder: clock %d nready %d\n", clock, nready);
6616 for (i=0; i<nready; i++)
6617 mep_print_sched_insn (dump, ready[i]);
6618 fprintf (dump, "\n");
6619 }
6620
6621 if (!mep_vliw_function_p (cfun->decl))
6622 return 1;
6623 if (nready < 2)
6624 return 1;
6625
6626 /* IVC2 uses a DFA to determine what's ready and what's not. */
6627 if (TARGET_IVC2)
6628 return nready;
6629
6630 /* We can issue either a core or coprocessor instruction.
6631 Look for a matched pair of insns to reorder. If we don't
6632 find any, don't second-guess the scheduler's priorities. */
6633
6634 if ((core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 2))
6635 && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP,
6636 TARGET_OPT_VL64 ? 6 : 2)))
6637 ;
6638 else if (TARGET_OPT_VL64
6639 && (core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 4))
6640 && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP, 4)))
6641 ;
6642 else
6643 /* We didn't find a pair. Issue the single insn at the head
6644 of the ready list. */
6645 return 1;
6646
6647 /* Reorder the two insns first. */
6648 mep_move_ready_insn (ready, nready, core_insn);
6649 mep_move_ready_insn (ready, nready - 1, cop_insn);
6650 return 2;
6651 }
6652
6653 /* A for_each_rtx callback. Return true if *X is a register that is
6654 set by insn PREV. */
6655
6656 static int
6657 mep_store_find_set (rtx *x, void *prev)
6658 {
6659 return REG_P (*x) && reg_set_p (*x, (const_rtx) prev);
6660 }
6661
6662 /* Like mep_store_bypass_p, but takes a pattern as the second argument,
6663 not the containing insn. */
6664
6665 static bool
6666 mep_store_data_bypass_1 (rtx prev, rtx pat)
6667 {
6668 /* Cope with intrinsics like swcpa. */
6669 if (GET_CODE (pat) == PARALLEL)
6670 {
6671 int i;
6672
6673 for (i = 0; i < XVECLEN (pat, 0); i++)
6674 if (mep_store_data_bypass_p (prev, XVECEXP (pat, 0, i)))
6675 return true;
6676
6677 return false;
6678 }
6679
6680 /* Check for some sort of store. */
6681 if (GET_CODE (pat) != SET
6682 || GET_CODE (SET_DEST (pat)) != MEM)
6683 return false;
6684
6685 /* Intrinsics use patterns of the form (set (mem (scratch)) (unspec ...)).
6686 The first operand to the unspec is the store data and the other operands
6687 are used to calculate the address. */
6688 if (GET_CODE (SET_SRC (pat)) == UNSPEC)
6689 {
6690 rtx src;
6691 int i;
6692
6693 src = SET_SRC (pat);
6694 for (i = 1; i < XVECLEN (src, 0); i++)
6695 if (for_each_rtx (&XVECEXP (src, 0, i), mep_store_find_set, prev))
6696 return false;
6697
6698 return true;
6699 }
6700
6701 /* Otherwise just check that PREV doesn't modify any register mentioned
6702 in the memory destination. */
6703 return !for_each_rtx (&SET_DEST (pat), mep_store_find_set, prev);
6704 }
6705
6706 /* Return true if INSN is a store instruction and if the store address
6707 has no true dependence on PREV. */
6708
6709 bool
6710 mep_store_data_bypass_p (rtx prev, rtx insn)
6711 {
6712 return INSN_P (insn) ? mep_store_data_bypass_1 (prev, PATTERN (insn)) : false;
6713 }
6714
6715 /* A for_each_rtx subroutine of mep_mul_hilo_bypass_p. Return 1 if *X
6716 is a register other than LO or HI and if PREV sets *X. */
6717
6718 static int
6719 mep_mul_hilo_bypass_1 (rtx *x, void *prev)
6720 {
6721 return (REG_P (*x)
6722 && REGNO (*x) != LO_REGNO
6723 && REGNO (*x) != HI_REGNO
6724 && reg_set_p (*x, (const_rtx) prev));
6725 }
6726
6727 /* Return true if, apart from HI/LO, there are no true dependencies
6728 between multiplication instructions PREV and INSN. */
6729
6730 bool
6731 mep_mul_hilo_bypass_p (rtx prev, rtx insn)
6732 {
6733 rtx pat;
6734
6735 pat = PATTERN (insn);
6736 if (GET_CODE (pat) == PARALLEL)
6737 pat = XVECEXP (pat, 0, 0);
6738 return (GET_CODE (pat) == SET
6739 && !for_each_rtx (&SET_SRC (pat), mep_mul_hilo_bypass_1, prev));
6740 }
6741
6742 /* Return true if INSN is an ldc instruction that issues to the
6743 MeP-h1 integer pipeline. This is true for instructions that
6744 read from PSW, LP, SAR, HI and LO. */
6745
6746 bool
6747 mep_ipipe_ldc_p (rtx insn)
6748 {
6749 rtx pat, src;
6750
6751 pat = PATTERN (insn);
6752
6753 /* Cope with instrinsics that set both a hard register and its shadow.
6754 The set of the hard register comes first. */
6755 if (GET_CODE (pat) == PARALLEL)
6756 pat = XVECEXP (pat, 0, 0);
6757
6758 if (GET_CODE (pat) == SET)
6759 {
6760 src = SET_SRC (pat);
6761
6762 /* Cope with intrinsics. The first operand to the unspec is
6763 the source register. */
6764 if (GET_CODE (src) == UNSPEC || GET_CODE (src) == UNSPEC_VOLATILE)
6765 src = XVECEXP (src, 0, 0);
6766
6767 if (REG_P (src))
6768 switch (REGNO (src))
6769 {
6770 case PSW_REGNO:
6771 case LP_REGNO:
6772 case SAR_REGNO:
6773 case HI_REGNO:
6774 case LO_REGNO:
6775 return true;
6776 }
6777 }
6778 return false;
6779 }
6780
6781 /* Create a VLIW bundle from core instruction CORE and coprocessor
6782 instruction COP. COP always satisfies INSN_P, but CORE can be
6783 either a new pattern or an existing instruction.
6784
6785 Emit the bundle in place of COP and return it. */
6786
6787 static rtx
6788 mep_make_bundle (rtx core, rtx cop)
6789 {
6790 rtx insn;
6791
6792 /* If CORE is an existing instruction, remove it, otherwise put
6793 the new pattern in an INSN harness. */
6794 if (INSN_P (core))
6795 remove_insn (core);
6796 else
6797 core = make_insn_raw (core);
6798
6799 /* Generate the bundle sequence and replace COP with it. */
6800 insn = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (2, core, cop));
6801 insn = emit_insn_after (insn, cop);
6802 remove_insn (cop);
6803
6804 /* Set up the links of the insns inside the SEQUENCE. */
6805 PREV_INSN (core) = PREV_INSN (insn);
6806 NEXT_INSN (core) = cop;
6807 PREV_INSN (cop) = core;
6808 NEXT_INSN (cop) = NEXT_INSN (insn);
6809
6810 /* Set the VLIW flag for the coprocessor instruction. */
6811 PUT_MODE (core, VOIDmode);
6812 PUT_MODE (cop, BImode);
6813
6814 /* Derive a location for the bundle. Individual instructions cannot
6815 have their own location because there can be no assembler labels
6816 between CORE and COP. */
6817 INSN_LOCATION (insn) = INSN_LOCATION (INSN_LOCATION (core) ? core : cop);
6818 INSN_LOCATION (core) = 0;
6819 INSN_LOCATION (cop) = 0;
6820
6821 return insn;
6822 }
6823
6824 /* A helper routine for ms1_insn_dependent_p called through note_stores. */
6825
6826 static void
6827 mep_insn_dependent_p_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
6828 {
6829 rtx * pinsn = (rtx *) data;
6830
6831 if (*pinsn && reg_mentioned_p (x, *pinsn))
6832 *pinsn = NULL_RTX;
6833 }
6834
6835 /* Return true if anything in insn X is (anti,output,true) dependent on
6836 anything in insn Y. */
6837
6838 static int
6839 mep_insn_dependent_p (rtx x, rtx y)
6840 {
6841 rtx tmp;
6842
6843 gcc_assert (INSN_P (x));
6844 gcc_assert (INSN_P (y));
6845
6846 tmp = PATTERN (y);
6847 note_stores (PATTERN (x), mep_insn_dependent_p_1, &tmp);
6848 if (tmp == NULL_RTX)
6849 return 1;
6850
6851 tmp = PATTERN (x);
6852 note_stores (PATTERN (y), mep_insn_dependent_p_1, &tmp);
6853 if (tmp == NULL_RTX)
6854 return 1;
6855
6856 return 0;
6857 }
6858
6859 static int
6860 core_insn_p (rtx insn)
6861 {
6862 if (GET_CODE (PATTERN (insn)) == USE)
6863 return 0;
6864 if (get_attr_slot (insn) == SLOT_CORE)
6865 return 1;
6866 return 0;
6867 }
6868
6869 /* Mark coprocessor instructions that can be bundled together with
6870 the immediately preceding core instruction. This is later used
6871 to emit the "+" that tells the assembler to create a VLIW insn.
6872
6873 For unbundled insns, the assembler will automatically add coprocessor
6874 nops, and 16-bit core nops. Due to an apparent oversight in the
6875 spec, the assembler will _not_ automatically add 32-bit core nops,
6876 so we have to emit those here.
6877
6878 Called from mep_insn_reorg. */
6879
6880 static void
6881 mep_bundle_insns (rtx insns)
6882 {
6883 rtx insn, last = NULL_RTX, first = NULL_RTX;
6884 int saw_scheduling = 0;
6885
6886 /* Only do bundling if we're in vliw mode. */
6887 if (!mep_vliw_function_p (cfun->decl))
6888 return;
6889
6890 /* The first insn in a bundle are TImode, the remainder are
6891 VOIDmode. After this function, the first has VOIDmode and the
6892 rest have BImode. */
6893
6894 /* Note: this doesn't appear to be true for JUMP_INSNs. */
6895
6896 /* First, move any NOTEs that are within a bundle, to the beginning
6897 of the bundle. */
6898 for (insn = insns; insn ; insn = NEXT_INSN (insn))
6899 {
6900 if (NOTE_P (insn) && first)
6901 /* Don't clear FIRST. */;
6902
6903 else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == TImode)
6904 first = insn;
6905
6906 else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == VOIDmode && first)
6907 {
6908 rtx note, prev;
6909
6910 /* INSN is part of a bundle; FIRST is the first insn in that
6911 bundle. Move all intervening notes out of the bundle.
6912 In addition, since the debug pass may insert a label
6913 whenever the current line changes, set the location info
6914 for INSN to match FIRST. */
6915
6916 INSN_LOCATION (insn) = INSN_LOCATION (first);
6917
6918 note = PREV_INSN (insn);
6919 while (note && note != first)
6920 {
6921 prev = PREV_INSN (note);
6922
6923 if (NOTE_P (note))
6924 {
6925 /* Remove NOTE from here... */
6926 PREV_INSN (NEXT_INSN (note)) = PREV_INSN (note);
6927 NEXT_INSN (PREV_INSN (note)) = NEXT_INSN (note);
6928 /* ...and put it in here. */
6929 NEXT_INSN (note) = first;
6930 PREV_INSN (note) = PREV_INSN (first);
6931 NEXT_INSN (PREV_INSN (note)) = note;
6932 PREV_INSN (NEXT_INSN (note)) = note;
6933 }
6934
6935 note = prev;
6936 }
6937 }
6938
6939 else if (!NONJUMP_INSN_P (insn))
6940 first = 0;
6941 }
6942
6943 /* Now fix up the bundles. */
6944 for (insn = insns; insn ; insn = NEXT_INSN (insn))
6945 {
6946 if (NOTE_P (insn))
6947 continue;
6948
6949 if (!NONJUMP_INSN_P (insn))
6950 {
6951 last = 0;
6952 continue;
6953 }
6954
6955 /* If we're not optimizing enough, there won't be scheduling
6956 info. We detect that here. */
6957 if (GET_MODE (insn) == TImode)
6958 saw_scheduling = 1;
6959 if (!saw_scheduling)
6960 continue;
6961
6962 if (TARGET_IVC2)
6963 {
6964 rtx core_insn = NULL_RTX;
6965
6966 /* IVC2 slots are scheduled by DFA, so we just accept
6967 whatever the scheduler gives us. However, we must make
6968 sure the core insn (if any) is the first in the bundle.
6969 The IVC2 assembler can insert whatever NOPs are needed,
6970 and allows a COP insn to be first. */
6971
6972 if (NONJUMP_INSN_P (insn)
6973 && GET_CODE (PATTERN (insn)) != USE
6974 && GET_MODE (insn) == TImode)
6975 {
6976 for (last = insn;
6977 NEXT_INSN (last)
6978 && GET_MODE (NEXT_INSN (last)) == VOIDmode
6979 && NONJUMP_INSN_P (NEXT_INSN (last));
6980 last = NEXT_INSN (last))
6981 {
6982 if (core_insn_p (last))
6983 core_insn = last;
6984 }
6985 if (core_insn_p (last))
6986 core_insn = last;
6987
6988 if (core_insn && core_insn != insn)
6989 {
6990 /* Swap core insn to first in the bundle. */
6991
6992 /* Remove core insn. */
6993 if (PREV_INSN (core_insn))
6994 NEXT_INSN (PREV_INSN (core_insn)) = NEXT_INSN (core_insn);
6995 if (NEXT_INSN (core_insn))
6996 PREV_INSN (NEXT_INSN (core_insn)) = PREV_INSN (core_insn);
6997
6998 /* Re-insert core insn. */
6999 PREV_INSN (core_insn) = PREV_INSN (insn);
7000 NEXT_INSN (core_insn) = insn;
7001
7002 if (PREV_INSN (core_insn))
7003 NEXT_INSN (PREV_INSN (core_insn)) = core_insn;
7004 PREV_INSN (insn) = core_insn;
7005
7006 PUT_MODE (core_insn, TImode);
7007 PUT_MODE (insn, VOIDmode);
7008 }
7009 }
7010
7011 /* The first insn has TImode, the rest have VOIDmode */
7012 if (GET_MODE (insn) == TImode)
7013 PUT_MODE (insn, VOIDmode);
7014 else
7015 PUT_MODE (insn, BImode);
7016 continue;
7017 }
7018
7019 PUT_MODE (insn, VOIDmode);
7020 if (recog_memoized (insn) >= 0
7021 && get_attr_slot (insn) == SLOT_COP)
7022 {
7023 if (GET_CODE (insn) == JUMP_INSN
7024 || ! last
7025 || recog_memoized (last) < 0
7026 || get_attr_slot (last) != SLOT_CORE
7027 || (get_attr_length (insn)
7028 != (TARGET_OPT_VL64 ? 8 : 4) - get_attr_length (last))
7029 || mep_insn_dependent_p (insn, last))
7030 {
7031 switch (get_attr_length (insn))
7032 {
7033 case 8:
7034 break;
7035 case 6:
7036 insn = mep_make_bundle (gen_nop (), insn);
7037 break;
7038 case 4:
7039 if (TARGET_OPT_VL64)
7040 insn = mep_make_bundle (gen_nop32 (), insn);
7041 break;
7042 case 2:
7043 if (TARGET_OPT_VL64)
7044 error ("2 byte cop instructions are"
7045 " not allowed in 64-bit VLIW mode");
7046 else
7047 insn = mep_make_bundle (gen_nop (), insn);
7048 break;
7049 default:
7050 error ("unexpected %d byte cop instruction",
7051 get_attr_length (insn));
7052 break;
7053 }
7054 }
7055 else
7056 insn = mep_make_bundle (last, insn);
7057 }
7058
7059 last = insn;
7060 }
7061 }
7062
7063
7064 /* Try to instantiate INTRINSIC with the operands given in OPERANDS.
7065 Return true on success. This function can fail if the intrinsic
7066 is unavailable or if the operands don't satisfy their predicates. */
7067
7068 bool
7069 mep_emit_intrinsic (int intrinsic, const rtx *operands)
7070 {
7071 const struct cgen_insn *cgen_insn;
7072 const struct insn_data_d *idata;
7073 rtx newop[10];
7074 int i;
7075
7076 if (!mep_get_intrinsic_insn (intrinsic, &cgen_insn))
7077 return false;
7078
7079 idata = &insn_data[cgen_insn->icode];
7080 for (i = 0; i < idata->n_operands; i++)
7081 {
7082 newop[i] = mep_convert_arg (idata->operand[i].mode, operands[i]);
7083 if (!idata->operand[i].predicate (newop[i], idata->operand[i].mode))
7084 return false;
7085 }
7086
7087 emit_insn (idata->genfun (newop[0], newop[1], newop[2],
7088 newop[3], newop[4], newop[5],
7089 newop[6], newop[7], newop[8]));
7090
7091 return true;
7092 }
7093
7094
7095 /* Apply the given unary intrinsic to OPERANDS[1] and store it on
7096 OPERANDS[0]. Report an error if the instruction could not
7097 be synthesized. OPERANDS[1] is a register_operand. For sign
7098 and zero extensions, it may be smaller than SImode. */
7099
7100 bool
7101 mep_expand_unary_intrinsic (int ATTRIBUTE_UNUSED intrinsic,
7102 rtx * operands ATTRIBUTE_UNUSED)
7103 {
7104 return false;
7105 }
7106
7107
7108 /* Likewise, but apply a binary operation to OPERANDS[1] and
7109 OPERANDS[2]. OPERANDS[1] is a register_operand, OPERANDS[2]
7110 can be a general_operand.
7111
7112 IMMEDIATE and IMMEDIATE3 are intrinsics that take an immediate
7113 third operand. REG and REG3 take register operands only. */
7114
7115 bool
7116 mep_expand_binary_intrinsic (int ATTRIBUTE_UNUSED immediate,
7117 int ATTRIBUTE_UNUSED immediate3,
7118 int ATTRIBUTE_UNUSED reg,
7119 int ATTRIBUTE_UNUSED reg3,
7120 rtx * operands ATTRIBUTE_UNUSED)
7121 {
7122 return false;
7123 }
7124
7125 static bool
7126 mep_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
7127 int opno ATTRIBUTE_UNUSED, int *total,
7128 bool ATTRIBUTE_UNUSED speed_t)
7129 {
7130 switch (code)
7131 {
7132 case CONST_INT:
7133 if (INTVAL (x) >= -128 && INTVAL (x) < 127)
7134 *total = 0;
7135 else if (INTVAL (x) >= -32768 && INTVAL (x) < 65536)
7136 *total = 1;
7137 else
7138 *total = 3;
7139 return true;
7140
7141 case SYMBOL_REF:
7142 *total = optimize_size ? COSTS_N_INSNS (0) : COSTS_N_INSNS (1);
7143 return true;
7144
7145 case MULT:
7146 *total = (GET_CODE (XEXP (x, 1)) == CONST_INT
7147 ? COSTS_N_INSNS (3)
7148 : COSTS_N_INSNS (2));
7149 return true;
7150 }
7151 return false;
7152 }
7153
7154 static int
7155 mep_address_cost (rtx addr ATTRIBUTE_UNUSED,
7156 enum machine_mode mode ATTRIBUTE_UNUSED,
7157 addr_space_t as ATTRIBUTE_UNUSED,
7158 bool ATTRIBUTE_UNUSED speed_p)
7159 {
7160 return 1;
7161 }
7162
7163 static void
7164 mep_asm_init_sections (void)
7165 {
7166 based_section
7167 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7168 "\t.section .based,\"aw\"");
7169
7170 tinybss_section
7171 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op,
7172 "\t.section .sbss,\"aw\"");
7173
7174 sdata_section
7175 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7176 "\t.section .sdata,\"aw\",@progbits");
7177
7178 far_section
7179 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7180 "\t.section .far,\"aw\"");
7181
7182 farbss_section
7183 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op,
7184 "\t.section .farbss,\"aw\"");
7185
7186 frodata_section
7187 = get_unnamed_section (0, output_section_asm_op,
7188 "\t.section .frodata,\"a\"");
7189
7190 srodata_section
7191 = get_unnamed_section (0, output_section_asm_op,
7192 "\t.section .srodata,\"a\"");
7193
7194 vtext_section
7195 = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op,
7196 "\t.section .vtext,\"axv\"\n\t.vliw");
7197
7198 vftext_section
7199 = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op,
7200 "\t.section .vftext,\"axv\"\n\t.vliw");
7201
7202 ftext_section
7203 = get_unnamed_section (SECTION_CODE, output_section_asm_op,
7204 "\t.section .ftext,\"ax\"\n\t.core");
7205
7206 }
7207 \f
7208 /* Initialize the GCC target structure. */
7209
7210 #undef TARGET_ASM_FUNCTION_PROLOGUE
7211 #define TARGET_ASM_FUNCTION_PROLOGUE mep_start_function
7212 #undef TARGET_ATTRIBUTE_TABLE
7213 #define TARGET_ATTRIBUTE_TABLE mep_attribute_table
7214 #undef TARGET_COMP_TYPE_ATTRIBUTES
7215 #define TARGET_COMP_TYPE_ATTRIBUTES mep_comp_type_attributes
7216 #undef TARGET_INSERT_ATTRIBUTES
7217 #define TARGET_INSERT_ATTRIBUTES mep_insert_attributes
7218 #undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
7219 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P mep_function_attribute_inlinable_p
7220 #undef TARGET_CAN_INLINE_P
7221 #define TARGET_CAN_INLINE_P mep_can_inline_p
7222 #undef TARGET_SECTION_TYPE_FLAGS
7223 #define TARGET_SECTION_TYPE_FLAGS mep_section_type_flags
7224 #undef TARGET_ASM_NAMED_SECTION
7225 #define TARGET_ASM_NAMED_SECTION mep_asm_named_section
7226 #undef TARGET_INIT_BUILTINS
7227 #define TARGET_INIT_BUILTINS mep_init_builtins
7228 #undef TARGET_EXPAND_BUILTIN
7229 #define TARGET_EXPAND_BUILTIN mep_expand_builtin
7230 #undef TARGET_SCHED_ADJUST_COST
7231 #define TARGET_SCHED_ADJUST_COST mep_adjust_cost
7232 #undef TARGET_SCHED_ISSUE_RATE
7233 #define TARGET_SCHED_ISSUE_RATE mep_issue_rate
7234 #undef TARGET_SCHED_REORDER
7235 #define TARGET_SCHED_REORDER mep_sched_reorder
7236 #undef TARGET_STRIP_NAME_ENCODING
7237 #define TARGET_STRIP_NAME_ENCODING mep_strip_name_encoding
7238 #undef TARGET_ASM_SELECT_SECTION
7239 #define TARGET_ASM_SELECT_SECTION mep_select_section
7240 #undef TARGET_ASM_UNIQUE_SECTION
7241 #define TARGET_ASM_UNIQUE_SECTION mep_unique_section
7242 #undef TARGET_ENCODE_SECTION_INFO
7243 #define TARGET_ENCODE_SECTION_INFO mep_encode_section_info
7244 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
7245 #define TARGET_FUNCTION_OK_FOR_SIBCALL mep_function_ok_for_sibcall
7246 #undef TARGET_RTX_COSTS
7247 #define TARGET_RTX_COSTS mep_rtx_cost
7248 #undef TARGET_ADDRESS_COST
7249 #define TARGET_ADDRESS_COST mep_address_cost
7250 #undef TARGET_MACHINE_DEPENDENT_REORG
7251 #define TARGET_MACHINE_DEPENDENT_REORG mep_reorg
7252 #undef TARGET_SETUP_INCOMING_VARARGS
7253 #define TARGET_SETUP_INCOMING_VARARGS mep_setup_incoming_varargs
7254 #undef TARGET_PASS_BY_REFERENCE
7255 #define TARGET_PASS_BY_REFERENCE mep_pass_by_reference
7256 #undef TARGET_FUNCTION_ARG
7257 #define TARGET_FUNCTION_ARG mep_function_arg
7258 #undef TARGET_FUNCTION_ARG_ADVANCE
7259 #define TARGET_FUNCTION_ARG_ADVANCE mep_function_arg_advance
7260 #undef TARGET_VECTOR_MODE_SUPPORTED_P
7261 #define TARGET_VECTOR_MODE_SUPPORTED_P mep_vector_mode_supported_p
7262 #undef TARGET_OPTION_OVERRIDE
7263 #define TARGET_OPTION_OVERRIDE mep_option_override
7264 #undef TARGET_ALLOCATE_INITIAL_VALUE
7265 #define TARGET_ALLOCATE_INITIAL_VALUE mep_allocate_initial_value
7266 #undef TARGET_ASM_INIT_SECTIONS
7267 #define TARGET_ASM_INIT_SECTIONS mep_asm_init_sections
7268 #undef TARGET_RETURN_IN_MEMORY
7269 #define TARGET_RETURN_IN_MEMORY mep_return_in_memory
7270 #undef TARGET_NARROW_VOLATILE_BITFIELD
7271 #define TARGET_NARROW_VOLATILE_BITFIELD mep_narrow_volatile_bitfield
7272 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
7273 #define TARGET_EXPAND_BUILTIN_SAVEREGS mep_expand_builtin_saveregs
7274 #undef TARGET_BUILD_BUILTIN_VA_LIST
7275 #define TARGET_BUILD_BUILTIN_VA_LIST mep_build_builtin_va_list
7276 #undef TARGET_EXPAND_BUILTIN_VA_START
7277 #define TARGET_EXPAND_BUILTIN_VA_START mep_expand_va_start
7278 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
7279 #define TARGET_GIMPLIFY_VA_ARG_EXPR mep_gimplify_va_arg_expr
7280 #undef TARGET_CAN_ELIMINATE
7281 #define TARGET_CAN_ELIMINATE mep_can_eliminate
7282 #undef TARGET_CONDITIONAL_REGISTER_USAGE
7283 #define TARGET_CONDITIONAL_REGISTER_USAGE mep_conditional_register_usage
7284 #undef TARGET_TRAMPOLINE_INIT
7285 #define TARGET_TRAMPOLINE_INIT mep_trampoline_init
7286 #undef TARGET_LEGITIMATE_CONSTANT_P
7287 #define TARGET_LEGITIMATE_CONSTANT_P mep_legitimate_constant_p
7288
7289 struct gcc_target targetm = TARGET_INITIALIZER;
7290
7291 #include "gt-mep.h"