* target-def.h (TARGET_HAVE_NAMED_SECTIONS): Move to
[official-gcc.git] / gcc / config / mep / mep.c
blob81d902db2e99d0eb2a2f2cfdc4dc46433ad57013
1 /* Definitions for Toshiba Media Processor
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011
4 Free Software Foundation, Inc.
5 Contributed by Red Hat, Inc.
7 This file is part of GCC.
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.
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.
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/>. */
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 "integrate.h"
49 #include "target.h"
50 #include "target-def.h"
51 #include "langhooks.h"
52 #include "df.h"
53 #include "gimple.h"
54 #include "opts.h"
56 /* Structure of this file:
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. */
72 /* Symbol encodings:
74 Symbols are encoded as @ <char> . <name> where <char> is one of these:
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) */
84 struct GTY(()) machine_function
86 int mep_frame_pointer_needed;
88 /* For varargs. */
89 int arg_regs_to_save;
90 int regsave_filler;
91 int frame_filler;
92 int frame_locked;
94 /* Records __builtin_return address. */
95 rtx eh_stack_adjust;
97 int reg_save_size;
98 int reg_save_slot[FIRST_PSEUDO_REGISTER];
99 unsigned char reg_saved[FIRST_PSEUDO_REGISTER];
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;
106 /* Likewise, for disinterrupt attribute. */
107 int disable_interrupts;
109 /* Number of doloop tags used so far. */
110 int doloop_tags;
112 /* True if the last tag was allocated to a doloop_end. */
113 bool doloop_tag_from_end;
115 /* True if reload changes $TP. */
116 bool reload_changes_tp;
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;
123 #define MEP_CONTROL_REG(x) \
124 (GET_CODE (x) == REG && ANY_CONTROL_REGNO_P (REGNO (x)))
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;
133 static GTY(()) section * vtext_section;
134 static GTY(()) section * vftext_section;
135 static GTY(()) section * ftext_section;
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 *, bool);
215 static int mep_address_cost (rtx, bool);
216 static void mep_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
217 tree, int *, int);
218 static bool mep_pass_by_reference (CUMULATIVE_ARGS * cum, enum machine_mode,
219 const_tree, bool);
220 static rtx mep_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
221 const_tree, bool);
222 static void mep_function_arg_advance (CUMULATIVE_ARGS *, 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);
237 #define WANT_GCC_DEFINITIONS
238 #include "mep-intrin.h"
239 #undef WANT_GCC_DEFINITIONS
242 /* Command Line Option Support. */
244 char mep_leaf_registers [FIRST_PSEUDO_REGISTER];
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;
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;
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
270 static void
271 mep_set_leaf_registers (int enable)
273 int i;
275 if (mep_leaf_registers[0] != enable)
276 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
277 mep_leaf_registers[i] = enable;
280 static void
281 mep_conditional_register_usage (void)
283 int i;
285 if (!TARGET_OPT_MULT && !TARGET_OPT_DIV)
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;
293 for (i = FIRST_SHADOW_REGISTER; i <= LAST_SHADOW_REGISTER; i++)
294 global_regs[i] = 1;
297 static void
298 mep_option_override (void)
300 unsigned int i;
301 int j;
302 cl_deferred_option *opt;
303 VEC(cl_deferred_option,heap) *vec
304 = (VEC(cl_deferred_option,heap) *) mep_deferred_options;
306 FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
308 switch (opt->opt_index)
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;
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");
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");
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;
347 default:
348 gcc_unreachable ();
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");
369 if (mep_const_section)
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");
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;
384 if (TARGET_64BIT_CR_REGS)
385 flag_split_wide_types = 0;
387 init_machine_status = mep_init_machine_status;
388 mep_init_intrinsics ();
391 /* Pattern Support - constraints, predicates, expanders. */
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. */
396 static bool
397 symbol_p (rtx x)
399 int c = GET_CODE (x);
401 return (c == CONST_INT
402 || c == CONST
403 || c == SYMBOL_REF);
406 static bool
407 symbolref_p (rtx x)
409 int c;
411 if (GET_CODE (x) != MEM)
412 return false;
414 c = GET_CODE (XEXP (x, 0));
415 return (c == CONST_INT
416 || c == CONST
417 || c == SYMBOL_REF);
420 /* static const char *reg_class_names[] = REG_CLASS_NAMES; */
422 #define GEN_REG(R, STRICT) \
423 (GR_REGNO_P (R) \
424 || (!STRICT \
425 && ((R) == ARG_POINTER_REGNUM \
426 || (R) >= FIRST_PSEUDO_REGISTER)))
428 static char pattern[12], *patternp;
429 static GTY(()) rtx patternr[12];
430 #define RTX_IS(x) (strcmp (pattern, x) == 0)
432 static void
433 encode_pattern_1 (rtx x)
435 int i;
437 if (patternp == pattern + sizeof (pattern) - 2)
439 patternp[-1] = '?';
440 return;
443 patternr[patternp-pattern] = x;
445 switch (GET_CODE (x))
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;
499 static void
500 encode_pattern (rtx x)
502 patternp = pattern;
503 encode_pattern_1 (x);
504 *patternp = 0;
508 mep_section_tag (rtx x)
510 const char *name;
512 while (1)
514 switch (GET_CODE (x))
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;
532 done:
533 if (GET_CODE (x) != SYMBOL_REF)
534 return 0;
535 name = XSTR (x, 0);
536 if (name[0] == '@' && name[2] == '.')
538 if (name[1] == 'i' || name[1] == 'I')
540 if (name[1] == 'I')
541 return 'f'; /* near */
542 return 'n'; /* far */
544 return name[1];
546 return 0;
550 mep_regno_reg_class (int regno)
552 switch (regno)
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;
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;
568 if (CR_REGNO_P (regno))
570 int i, j;
572 /* Search for the register amongst user-defined subclasses of
573 the coprocessor registers. */
574 for (i = USER0_REGS; i <= USER3_REGS; ++i)
576 if (! TEST_HARD_REG_BIT (reg_class_contents[i], regno))
577 continue;
578 for (j = 0; j < N_REG_CLASSES; ++j)
580 enum reg_class sub = reg_class_subclasses[i][j];
582 if (sub == LIM_REG_CLASSES)
583 return i;
584 if (TEST_HARD_REG_BIT (reg_class_contents[sub], regno))
585 break;
589 return LOADABLE_CR_REGNO_P (regno) ? LOADABLE_CR_REGS : CR_REGS;
592 if (CCR_REGNO_P (regno))
593 return CCR_REGS;
595 gcc_assert (regno >= FIRST_SHADOW_REGISTER && regno <= LAST_SHADOW_REGISTER);
596 return NO_REGS;
599 #if 0
601 mep_reg_class_from_constraint (int c, const char *str)
603 switch (c)
605 case 'a':
606 return SP_REGS;
607 case 'b':
608 return TP_REGS;
609 case 'c':
610 return CONTROL_REGS;
611 case 'd':
612 return HILO_REGS;
613 case 'e':
615 switch (str[1])
617 case 'm':
618 return LOADABLE_CR_REGS;
619 case 'x':
620 return mep_have_copro_copro_moves_p ? CR_REGS : NO_REGS;
621 case 'r':
622 return mep_have_core_copro_moves_p ? CR_REGS : NO_REGS;
623 default:
624 return NO_REGS;
627 case 'h':
628 return HI_REGS;
629 case 'j':
630 return RPC_REGS;
631 case 'l':
632 return LO_REGS;
633 case 't':
634 return TPREL_REGS;
635 case 'v':
636 return GP_REGS;
637 case 'x':
638 return CR_REGS;
639 case 'y':
640 return CCR_REGS;
641 case 'z':
642 return R0_REGS;
644 case 'A':
645 case 'B':
646 case 'C':
647 case 'D':
649 enum reg_class which = c - 'A' + USER0_REGS;
650 return (reg_class_size[which] > 0 ? which : NO_REGS);
653 default:
654 return NO_REGS;
658 bool
659 mep_const_ok_for_letter_p (HOST_WIDE_INT value, int c)
661 switch (c)
663 case 'I': return value >= -32768 && value < 32768;
664 case 'J': return value >= 0 && value < 65536;
665 case 'K': return value >= 0 && value < 0x01000000;
666 case 'L': return value >= -32 && value < 32;
667 case 'M': return value >= 0 && value < 32;
668 case 'N': return value >= 0 && value < 16;
669 case 'O':
670 if (value & 0xffff)
671 return false;
672 return value >= -2147483647-1 && value <= 2147483647;
673 default:
674 gcc_unreachable ();
678 bool
679 mep_extra_constraint (rtx value, int c)
681 encode_pattern (value);
683 switch (c)
685 case 'R':
686 /* For near symbols, like what call uses. */
687 if (GET_CODE (value) == REG)
688 return 0;
689 return mep_call_address_operand (value, GET_MODE (value));
691 case 'S':
692 /* For signed 8-bit immediates. */
693 return (GET_CODE (value) == CONST_INT
694 && INTVAL (value) >= -128
695 && INTVAL (value) <= 127);
697 case 'T':
698 /* For tp/gp relative symbol values. */
699 return (RTX_IS ("u3s") || RTX_IS ("u2s")
700 || RTX_IS ("+u3si") || RTX_IS ("+u2si"));
702 case 'U':
703 /* Non-absolute memories. */
704 return GET_CODE (value) == MEM && ! CONSTANT_P (XEXP (value, 0));
706 case 'W':
707 /* %hi(sym) */
708 return RTX_IS ("Hs");
710 case 'Y':
711 /* Register indirect. */
712 return RTX_IS ("mr");
714 case 'Z':
715 return mep_section_tag (value) == 'c' && RTX_IS ("ms");
718 return false;
720 #endif
722 #undef PASS
723 #undef FAIL
725 static bool
726 const_in_range (rtx x, int minv, int maxv)
728 return (GET_CODE (x) == CONST_INT
729 && INTVAL (x) >= minv
730 && INTVAL (x) <= maxv);
733 /* Given three integer registers DEST, SRC1 and SRC2, return an rtx X
734 such that "mulr DEST,X" will calculate DEST = SRC1 * SRC2. If a move
735 is needed, emit it before INSN if INSN is nonnull, otherwise emit it
736 at the end of the insn stream. */
739 mep_mulr_source (rtx insn, rtx dest, rtx src1, rtx src2)
741 if (rtx_equal_p (dest, src1))
742 return src2;
743 else if (rtx_equal_p (dest, src2))
744 return src1;
745 else
747 if (insn == 0)
748 emit_insn (gen_movsi (copy_rtx (dest), src1));
749 else
750 emit_insn_before (gen_movsi (copy_rtx (dest), src1), insn);
751 return src2;
755 /* Replace INSN's pattern with PATTERN, a multiplication PARALLEL.
756 Change the last element of PATTERN from (clobber (scratch:SI))
757 to (clobber (reg:SI HI_REGNO)). */
759 static void
760 mep_rewrite_mult (rtx insn, rtx pattern)
762 rtx hi_clobber;
764 hi_clobber = XVECEXP (pattern, 0, XVECLEN (pattern, 0) - 1);
765 XEXP (hi_clobber, 0) = gen_rtx_REG (SImode, HI_REGNO);
766 PATTERN (insn) = pattern;
767 INSN_CODE (insn) = -1;
770 /* Subroutine of mep_reuse_lo_p. Rewrite instruction INSN so that it
771 calculates SRC1 * SRC2 and stores the result in $lo. Also make it
772 store the result in DEST if nonnull. */
774 static void
775 mep_rewrite_mulsi3 (rtx insn, rtx dest, rtx src1, rtx src2)
777 rtx lo, pattern;
779 lo = gen_rtx_REG (SImode, LO_REGNO);
780 if (dest)
781 pattern = gen_mulsi3r (lo, dest, copy_rtx (dest),
782 mep_mulr_source (insn, dest, src1, src2));
783 else
784 pattern = gen_mulsi3_lo (lo, src1, src2);
785 mep_rewrite_mult (insn, pattern);
788 /* Like mep_rewrite_mulsi3, but calculate SRC1 * SRC2 + SRC3. First copy
789 SRC3 into $lo, then use either madd or maddr. The move into $lo will
790 be deleted by a peephole2 if SRC3 is already in $lo. */
792 static void
793 mep_rewrite_maddsi3 (rtx insn, rtx dest, rtx src1, rtx src2, rtx src3)
795 rtx lo, pattern;
797 lo = gen_rtx_REG (SImode, LO_REGNO);
798 emit_insn_before (gen_movsi (copy_rtx (lo), src3), insn);
799 if (dest)
800 pattern = gen_maddsi3r (lo, dest, copy_rtx (dest),
801 mep_mulr_source (insn, dest, src1, src2),
802 copy_rtx (lo));
803 else
804 pattern = gen_maddsi3_lo (lo, src1, src2, copy_rtx (lo));
805 mep_rewrite_mult (insn, pattern);
808 /* Return true if $lo has the same value as integer register GPR when
809 instruction INSN is reached. If necessary, rewrite the instruction
810 that sets $lo so that it uses a proper SET, not a CLOBBER. LO is an
811 rtx for (reg:SI LO_REGNO).
813 This function is intended to be used by the peephole2 pass. Since
814 that pass goes from the end of a basic block to the beginning, and
815 propagates liveness information on the way, there is no need to
816 update register notes here.
818 If GPR_DEAD_P is true on entry, and this function returns true,
819 then the caller will replace _every_ use of GPR in and after INSN
820 with LO. This means that if the instruction that sets $lo is a
821 mulr- or maddr-type instruction, we can rewrite it to use mul or
822 madd instead. In combination with the copy progagation pass,
823 this allows us to replace sequences like:
825 mov GPR,R1
826 mulr GPR,R2
828 with:
830 mul R1,R2
832 if GPR is no longer used. */
834 static bool
835 mep_reuse_lo_p_1 (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
839 insn = PREV_INSN (insn);
840 if (INSN_P (insn))
841 switch (recog_memoized (insn))
843 case CODE_FOR_mulsi3_1:
844 extract_insn (insn);
845 if (rtx_equal_p (recog_data.operand[0], gpr))
847 mep_rewrite_mulsi3 (insn,
848 gpr_dead_p ? NULL : recog_data.operand[0],
849 recog_data.operand[1],
850 recog_data.operand[2]);
851 return true;
853 return false;
855 case CODE_FOR_maddsi3:
856 extract_insn (insn);
857 if (rtx_equal_p (recog_data.operand[0], gpr))
859 mep_rewrite_maddsi3 (insn,
860 gpr_dead_p ? NULL : recog_data.operand[0],
861 recog_data.operand[1],
862 recog_data.operand[2],
863 recog_data.operand[3]);
864 return true;
866 return false;
868 case CODE_FOR_mulsi3r:
869 case CODE_FOR_maddsi3r:
870 extract_insn (insn);
871 return rtx_equal_p (recog_data.operand[1], gpr);
873 default:
874 if (reg_set_p (lo, insn)
875 || reg_set_p (gpr, insn)
876 || volatile_insn_p (PATTERN (insn)))
877 return false;
879 if (gpr_dead_p && reg_referenced_p (gpr, PATTERN (insn)))
880 gpr_dead_p = false;
881 break;
884 while (!NOTE_INSN_BASIC_BLOCK_P (insn));
885 return false;
888 /* A wrapper around mep_reuse_lo_p_1 that preserves recog_data. */
890 bool
891 mep_reuse_lo_p (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
893 bool result = mep_reuse_lo_p_1 (lo, gpr, insn, gpr_dead_p);
894 extract_insn (insn);
895 return result;
898 /* Return true if SET can be turned into a post-modify load or store
899 that adds OFFSET to GPR. In other words, return true if SET can be
900 changed into:
902 (parallel [SET (set GPR (plus:SI GPR OFFSET))]).
904 It's OK to change SET to an equivalent operation in order to
905 make it match. */
907 static bool
908 mep_use_post_modify_for_set_p (rtx set, rtx gpr, rtx offset)
910 rtx *reg, *mem;
911 unsigned int reg_bytes, mem_bytes;
912 enum machine_mode reg_mode, mem_mode;
914 /* Only simple SETs can be converted. */
915 if (GET_CODE (set) != SET)
916 return false;
918 /* Point REG to what we hope will be the register side of the set and
919 MEM to what we hope will be the memory side. */
920 if (GET_CODE (SET_DEST (set)) == MEM)
922 mem = &SET_DEST (set);
923 reg = &SET_SRC (set);
925 else
927 reg = &SET_DEST (set);
928 mem = &SET_SRC (set);
929 if (GET_CODE (*mem) == SIGN_EXTEND)
930 mem = &XEXP (*mem, 0);
933 /* Check that *REG is a suitable coprocessor register. */
934 if (GET_CODE (*reg) != REG || !LOADABLE_CR_REGNO_P (REGNO (*reg)))
935 return false;
937 /* Check that *MEM is a suitable memory reference. */
938 if (GET_CODE (*mem) != MEM || !rtx_equal_p (XEXP (*mem, 0), gpr))
939 return false;
941 /* Get the number of bytes in each operand. */
942 mem_bytes = GET_MODE_SIZE (GET_MODE (*mem));
943 reg_bytes = GET_MODE_SIZE (GET_MODE (*reg));
945 /* Check that OFFSET is suitably aligned. */
946 if (INTVAL (offset) & (mem_bytes - 1))
947 return false;
949 /* Convert *MEM to a normal integer mode. */
950 mem_mode = mode_for_size (mem_bytes * BITS_PER_UNIT, MODE_INT, 0);
951 *mem = change_address (*mem, mem_mode, NULL);
953 /* Adjust *REG as well. */
954 *reg = shallow_copy_rtx (*reg);
955 if (reg == &SET_DEST (set) && reg_bytes < UNITS_PER_WORD)
957 /* SET is a subword load. Convert it to an explicit extension. */
958 PUT_MODE (*reg, SImode);
959 *mem = gen_rtx_SIGN_EXTEND (SImode, *mem);
961 else
963 reg_mode = mode_for_size (reg_bytes * BITS_PER_UNIT, MODE_INT, 0);
964 PUT_MODE (*reg, reg_mode);
966 return true;
969 /* Return the effect of frame-related instruction INSN. */
971 static rtx
972 mep_frame_expr (rtx insn)
974 rtx note, expr;
976 note = find_reg_note (insn, REG_FRAME_RELATED_EXPR, 0);
977 expr = (note != 0 ? XEXP (note, 0) : copy_rtx (PATTERN (insn)));
978 RTX_FRAME_RELATED_P (expr) = 1;
979 return expr;
982 /* Merge instructions INSN1 and INSN2 using a PARALLEL. Store the
983 new pattern in INSN1; INSN2 will be deleted by the caller. */
985 static void
986 mep_make_parallel (rtx insn1, rtx insn2)
988 rtx expr;
990 if (RTX_FRAME_RELATED_P (insn2))
992 expr = mep_frame_expr (insn2);
993 if (RTX_FRAME_RELATED_P (insn1))
994 expr = gen_rtx_SEQUENCE (VOIDmode,
995 gen_rtvec (2, mep_frame_expr (insn1), expr));
996 set_unique_reg_note (insn1, REG_FRAME_RELATED_EXPR, expr);
997 RTX_FRAME_RELATED_P (insn1) = 1;
1000 PATTERN (insn1) = gen_rtx_PARALLEL (VOIDmode,
1001 gen_rtvec (2, PATTERN (insn1),
1002 PATTERN (insn2)));
1003 INSN_CODE (insn1) = -1;
1006 /* SET_INSN is an instruction that adds OFFSET to REG. Go back through
1007 the basic block to see if any previous load or store instruction can
1008 be persuaded to do SET_INSN as a side-effect. Return true if so. */
1010 static bool
1011 mep_use_post_modify_p_1 (rtx set_insn, rtx reg, rtx offset)
1013 rtx insn;
1015 insn = set_insn;
1018 insn = PREV_INSN (insn);
1019 if (INSN_P (insn))
1021 if (mep_use_post_modify_for_set_p (PATTERN (insn), reg, offset))
1023 mep_make_parallel (insn, set_insn);
1024 return true;
1027 if (reg_set_p (reg, insn)
1028 || reg_referenced_p (reg, PATTERN (insn))
1029 || volatile_insn_p (PATTERN (insn)))
1030 return false;
1033 while (!NOTE_INSN_BASIC_BLOCK_P (insn));
1034 return false;
1037 /* A wrapper around mep_use_post_modify_p_1 that preserves recog_data. */
1039 bool
1040 mep_use_post_modify_p (rtx insn, rtx reg, rtx offset)
1042 bool result = mep_use_post_modify_p_1 (insn, reg, offset);
1043 extract_insn (insn);
1044 return result;
1047 bool
1048 mep_allow_clip (rtx ux, rtx lx, int s)
1050 HOST_WIDE_INT u = INTVAL (ux);
1051 HOST_WIDE_INT l = INTVAL (lx);
1052 int i;
1054 if (!TARGET_OPT_CLIP)
1055 return false;
1057 if (s)
1059 for (i = 0; i < 30; i ++)
1060 if ((u == ((HOST_WIDE_INT) 1 << i) - 1)
1061 && (l == - ((HOST_WIDE_INT) 1 << i)))
1062 return true;
1064 else
1066 if (l != 0)
1067 return false;
1069 for (i = 0; i < 30; i ++)
1070 if ((u == ((HOST_WIDE_INT) 1 << i) - 1))
1071 return true;
1073 return false;
1076 bool
1077 mep_bit_position_p (rtx x, bool looking_for)
1079 if (GET_CODE (x) != CONST_INT)
1080 return false;
1081 switch ((int) INTVAL(x) & 0xff)
1083 case 0x01: case 0x02: case 0x04: case 0x08:
1084 case 0x10: case 0x20: case 0x40: case 0x80:
1085 return looking_for;
1086 case 0xfe: case 0xfd: case 0xfb: case 0xf7:
1087 case 0xef: case 0xdf: case 0xbf: case 0x7f:
1088 return !looking_for;
1090 return false;
1093 static bool
1094 move_needs_splitting (rtx dest, rtx src,
1095 enum machine_mode mode ATTRIBUTE_UNUSED)
1097 int s = mep_section_tag (src);
1099 while (1)
1101 if (GET_CODE (src) == CONST
1102 || GET_CODE (src) == MEM)
1103 src = XEXP (src, 0);
1104 else if (GET_CODE (src) == SYMBOL_REF
1105 || GET_CODE (src) == LABEL_REF
1106 || GET_CODE (src) == PLUS)
1107 break;
1108 else
1109 return false;
1111 if (s == 'f'
1112 || (GET_CODE (src) == PLUS
1113 && GET_CODE (XEXP (src, 1)) == CONST_INT
1114 && (INTVAL (XEXP (src, 1)) < -65536
1115 || INTVAL (XEXP (src, 1)) > 0xffffff))
1116 || (GET_CODE (dest) == REG
1117 && REGNO (dest) > 7 && REGNO (dest) < FIRST_PSEUDO_REGISTER))
1118 return true;
1119 return false;
1122 bool
1123 mep_split_mov (rtx *operands, int symbolic)
1125 if (symbolic)
1127 if (move_needs_splitting (operands[0], operands[1], SImode))
1128 return true;
1129 return false;
1132 if (GET_CODE (operands[1]) != CONST_INT)
1133 return false;
1135 if (constraint_satisfied_p (operands[1], CONSTRAINT_I)
1136 || constraint_satisfied_p (operands[1], CONSTRAINT_J)
1137 || constraint_satisfied_p (operands[1], CONSTRAINT_O))
1138 return false;
1140 if (((!reload_completed && !reload_in_progress)
1141 || (REG_P (operands[0]) && REGNO (operands[0]) < 8))
1142 && constraint_satisfied_p (operands[1], CONSTRAINT_K))
1143 return false;
1145 return true;
1148 /* Irritatingly, the "jsrv" insn *toggles* PSW.OM rather than set
1149 it to one specific value. So the insn chosen depends on whether
1150 the source and destination modes match. */
1152 bool
1153 mep_vliw_mode_match (rtx tgt)
1155 bool src_vliw = mep_vliw_function_p (cfun->decl);
1156 bool tgt_vliw = INTVAL (tgt);
1158 return src_vliw == tgt_vliw;
1161 /* Like the above, but also test for near/far mismatches. */
1163 bool
1164 mep_vliw_jmp_match (rtx tgt)
1166 bool src_vliw = mep_vliw_function_p (cfun->decl);
1167 bool tgt_vliw = INTVAL (tgt);
1169 if (mep_section_tag (DECL_RTL (cfun->decl)) == 'f')
1170 return false;
1172 return src_vliw == tgt_vliw;
1175 bool
1176 mep_multi_slot (rtx x)
1178 return get_attr_slot (x) == SLOT_MULTI;
1181 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1183 static bool
1184 mep_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1186 /* We can't convert symbol values to gp- or tp-rel values after
1187 reload, as reload might have used $gp or $tp for other
1188 purposes. */
1189 if (GET_CODE (x) == SYMBOL_REF && (reload_in_progress || reload_completed))
1191 char e = mep_section_tag (x);
1192 return (e != 't' && e != 'b');
1194 return 1;
1197 /* Be careful not to use macros that need to be compiled one way for
1198 strict, and another way for not-strict, like REG_OK_FOR_BASE_P. */
1200 bool
1201 mep_legitimate_address (enum machine_mode mode, rtx x, int strict)
1203 int the_tag;
1205 #define DEBUG_LEGIT 0
1206 #if DEBUG_LEGIT
1207 fprintf (stderr, "legit: mode %s strict %d ", mode_name[mode], strict);
1208 debug_rtx (x);
1209 #endif
1211 if (GET_CODE (x) == LO_SUM
1212 && GET_CODE (XEXP (x, 0)) == REG
1213 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1214 && CONSTANT_P (XEXP (x, 1)))
1216 if (GET_MODE_SIZE (mode) > 4)
1218 /* We will end up splitting this, and lo_sums are not
1219 offsettable for us. */
1220 #if DEBUG_LEGIT
1221 fprintf(stderr, " - nope, %%lo(sym)[reg] not splittable\n");
1222 #endif
1223 return false;
1225 #if DEBUG_LEGIT
1226 fprintf (stderr, " - yup, %%lo(sym)[reg]\n");
1227 #endif
1228 return true;
1231 if (GET_CODE (x) == REG
1232 && GEN_REG (REGNO (x), strict))
1234 #if DEBUG_LEGIT
1235 fprintf (stderr, " - yup, [reg]\n");
1236 #endif
1237 return true;
1240 if (GET_CODE (x) == PLUS
1241 && GET_CODE (XEXP (x, 0)) == REG
1242 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1243 && const_in_range (XEXP (x, 1), -32768, 32767))
1245 #if DEBUG_LEGIT
1246 fprintf (stderr, " - yup, [reg+const]\n");
1247 #endif
1248 return true;
1251 if (GET_CODE (x) == PLUS
1252 && GET_CODE (XEXP (x, 0)) == REG
1253 && GEN_REG (REGNO (XEXP (x, 0)), strict)
1254 && GET_CODE (XEXP (x, 1)) == CONST
1255 && (GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
1256 || (GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
1257 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == UNSPEC
1258 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)))
1260 #if DEBUG_LEGIT
1261 fprintf (stderr, " - yup, [reg+unspec]\n");
1262 #endif
1263 return true;
1266 the_tag = mep_section_tag (x);
1268 if (the_tag == 'f')
1270 #if DEBUG_LEGIT
1271 fprintf (stderr, " - nope, [far]\n");
1272 #endif
1273 return false;
1276 if (mode == VOIDmode
1277 && GET_CODE (x) == SYMBOL_REF)
1279 #if DEBUG_LEGIT
1280 fprintf (stderr, " - yup, call [symbol]\n");
1281 #endif
1282 return true;
1285 if ((mode == SImode || mode == SFmode)
1286 && CONSTANT_P (x)
1287 && mep_legitimate_constant_p (mode, x)
1288 && the_tag != 't' && the_tag != 'b')
1290 if (GET_CODE (x) != CONST_INT
1291 || (INTVAL (x) <= 0xfffff
1292 && INTVAL (x) >= 0
1293 && (INTVAL (x) % 4) == 0))
1295 #if DEBUG_LEGIT
1296 fprintf (stderr, " - yup, [const]\n");
1297 #endif
1298 return true;
1302 #if DEBUG_LEGIT
1303 fprintf (stderr, " - nope.\n");
1304 #endif
1305 return false;
1309 mep_legitimize_reload_address (rtx *x, enum machine_mode mode, int opnum,
1310 int type_i,
1311 int ind_levels ATTRIBUTE_UNUSED)
1313 enum reload_type type = (enum reload_type) type_i;
1315 if (GET_CODE (*x) == PLUS
1316 && GET_CODE (XEXP (*x, 0)) == MEM
1317 && GET_CODE (XEXP (*x, 1)) == REG)
1319 /* GCC will by default copy the MEM into a REG, which results in
1320 an invalid address. For us, the best thing to do is move the
1321 whole expression to a REG. */
1322 push_reload (*x, NULL_RTX, x, NULL,
1323 GENERAL_REGS, mode, VOIDmode,
1324 0, 0, opnum, type);
1325 return 1;
1328 if (GET_CODE (*x) == PLUS
1329 && GET_CODE (XEXP (*x, 0)) == SYMBOL_REF
1330 && GET_CODE (XEXP (*x, 1)) == CONST_INT)
1332 char e = mep_section_tag (XEXP (*x, 0));
1334 if (e != 't' && e != 'b')
1336 /* GCC thinks that (sym+const) is a valid address. Well,
1337 sometimes it is, this time it isn't. The best thing to
1338 do is reload the symbol to a register, since reg+int
1339 tends to work, and we can't just add the symbol and
1340 constant anyway. */
1341 push_reload (XEXP (*x, 0), NULL_RTX, &(XEXP(*x, 0)), NULL,
1342 GENERAL_REGS, mode, VOIDmode,
1343 0, 0, opnum, type);
1344 return 1;
1347 return 0;
1351 mep_core_address_length (rtx insn, int opn)
1353 rtx set = single_set (insn);
1354 rtx mem = XEXP (set, opn);
1355 rtx other = XEXP (set, 1-opn);
1356 rtx addr = XEXP (mem, 0);
1358 if (register_operand (addr, Pmode))
1359 return 2;
1360 if (GET_CODE (addr) == PLUS)
1362 rtx addend = XEXP (addr, 1);
1364 gcc_assert (REG_P (XEXP (addr, 0)));
1366 switch (REGNO (XEXP (addr, 0)))
1368 case STACK_POINTER_REGNUM:
1369 if (GET_MODE_SIZE (GET_MODE (mem)) == 4
1370 && mep_imm7a4_operand (addend, VOIDmode))
1371 return 2;
1372 break;
1374 case 13: /* TP */
1375 gcc_assert (REG_P (other));
1377 if (REGNO (other) >= 8)
1378 break;
1380 if (GET_CODE (addend) == CONST
1381 && GET_CODE (XEXP (addend, 0)) == UNSPEC
1382 && XINT (XEXP (addend, 0), 1) == UNS_TPREL)
1383 return 2;
1385 if (GET_CODE (addend) == CONST_INT
1386 && INTVAL (addend) >= 0
1387 && INTVAL (addend) <= 127
1388 && INTVAL (addend) % GET_MODE_SIZE (GET_MODE (mem)) == 0)
1389 return 2;
1390 break;
1394 return 4;
1398 mep_cop_address_length (rtx insn, int opn)
1400 rtx set = single_set (insn);
1401 rtx mem = XEXP (set, opn);
1402 rtx addr = XEXP (mem, 0);
1404 if (GET_CODE (mem) != MEM)
1405 return 2;
1406 if (register_operand (addr, Pmode))
1407 return 2;
1408 if (GET_CODE (addr) == POST_INC)
1409 return 2;
1411 return 4;
1414 #define DEBUG_EXPAND_MOV 0
1415 bool
1416 mep_expand_mov (rtx *operands, enum machine_mode mode)
1418 int i, t;
1419 int tag[2];
1420 rtx tpsym, tpoffs;
1421 int post_reload = 0;
1423 tag[0] = mep_section_tag (operands[0]);
1424 tag[1] = mep_section_tag (operands[1]);
1426 if (!reload_in_progress
1427 && !reload_completed
1428 && GET_CODE (operands[0]) != REG
1429 && GET_CODE (operands[0]) != SUBREG
1430 && GET_CODE (operands[1]) != REG
1431 && GET_CODE (operands[1]) != SUBREG)
1432 operands[1] = copy_to_mode_reg (mode, operands[1]);
1434 #if DEBUG_EXPAND_MOV
1435 fprintf(stderr, "expand move %s %d\n", mode_name[mode],
1436 reload_in_progress || reload_completed);
1437 debug_rtx (operands[0]);
1438 debug_rtx (operands[1]);
1439 #endif
1441 if (mode == DImode || mode == DFmode)
1442 return false;
1444 if (reload_in_progress || reload_completed)
1446 rtx r;
1448 if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == TP_REGNO)
1449 cfun->machine->reload_changes_tp = true;
1451 if (tag[0] == 't' || tag[1] == 't')
1453 r = has_hard_reg_initial_val (Pmode, GP_REGNO);
1454 if (!r || GET_CODE (r) != REG || REGNO (r) != GP_REGNO)
1455 post_reload = 1;
1457 if (tag[0] == 'b' || tag[1] == 'b')
1459 r = has_hard_reg_initial_val (Pmode, TP_REGNO);
1460 if (!r || GET_CODE (r) != REG || REGNO (r) != TP_REGNO)
1461 post_reload = 1;
1463 if (cfun->machine->reload_changes_tp == true)
1464 post_reload = 1;
1467 if (!post_reload)
1469 rtx n;
1470 if (symbol_p (operands[1]))
1472 t = mep_section_tag (operands[1]);
1473 if (t == 'b' || t == 't')
1476 if (GET_CODE (operands[1]) == SYMBOL_REF)
1478 tpsym = operands[1];
1479 n = gen_rtx_UNSPEC (mode,
1480 gen_rtvec (1, operands[1]),
1481 t == 'b' ? UNS_TPREL : UNS_GPREL);
1482 n = gen_rtx_CONST (mode, n);
1484 else if (GET_CODE (operands[1]) == CONST
1485 && GET_CODE (XEXP (operands[1], 0)) == PLUS
1486 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
1487 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
1489 tpsym = XEXP (XEXP (operands[1], 0), 0);
1490 tpoffs = XEXP (XEXP (operands[1], 0), 1);
1491 n = gen_rtx_UNSPEC (mode,
1492 gen_rtvec (1, tpsym),
1493 t == 'b' ? UNS_TPREL : UNS_GPREL);
1494 n = gen_rtx_PLUS (mode, n, tpoffs);
1495 n = gen_rtx_CONST (mode, n);
1497 else if (GET_CODE (operands[1]) == CONST
1498 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
1499 return false;
1500 else
1502 error ("unusual TP-relative address");
1503 return false;
1506 n = gen_rtx_PLUS (mode, (t == 'b' ? mep_tp_rtx ()
1507 : mep_gp_rtx ()), n);
1508 n = emit_insn (gen_rtx_SET (mode, operands[0], n));
1509 #if DEBUG_EXPAND_MOV
1510 fprintf(stderr, "mep_expand_mov emitting ");
1511 debug_rtx(n);
1512 #endif
1513 return true;
1517 for (i=0; i < 2; i++)
1519 t = mep_section_tag (operands[i]);
1520 if (GET_CODE (operands[i]) == MEM && (t == 'b' || t == 't'))
1522 rtx sym, n, r;
1523 int u;
1525 sym = XEXP (operands[i], 0);
1526 if (GET_CODE (sym) == CONST
1527 && GET_CODE (XEXP (sym, 0)) == UNSPEC)
1528 sym = XVECEXP (XEXP (sym, 0), 0, 0);
1530 if (t == 'b')
1532 r = mep_tp_rtx ();
1533 u = UNS_TPREL;
1535 else
1537 r = mep_gp_rtx ();
1538 u = UNS_GPREL;
1541 n = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), u);
1542 n = gen_rtx_CONST (Pmode, n);
1543 n = gen_rtx_PLUS (Pmode, r, n);
1544 operands[i] = replace_equiv_address (operands[i], n);
1549 if ((GET_CODE (operands[1]) != REG
1550 && MEP_CONTROL_REG (operands[0]))
1551 || (GET_CODE (operands[0]) != REG
1552 && MEP_CONTROL_REG (operands[1])))
1554 rtx temp;
1555 #if DEBUG_EXPAND_MOV
1556 fprintf (stderr, "cr-mem, forcing op1 to reg\n");
1557 #endif
1558 temp = gen_reg_rtx (mode);
1559 emit_move_insn (temp, operands[1]);
1560 operands[1] = temp;
1563 if (symbolref_p (operands[0])
1564 && (mep_section_tag (XEXP (operands[0], 0)) == 'f'
1565 || (GET_MODE_SIZE (mode) != 4)))
1567 rtx temp;
1569 gcc_assert (!reload_in_progress && !reload_completed);
1571 temp = force_reg (Pmode, XEXP (operands[0], 0));
1572 operands[0] = replace_equiv_address (operands[0], temp);
1573 emit_move_insn (operands[0], operands[1]);
1574 return true;
1577 if (!post_reload && (tag[1] == 't' || tag[1] == 'b'))
1578 tag[1] = 0;
1580 if (symbol_p (operands[1])
1581 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1583 emit_insn (gen_movsi_topsym_s (operands[0], operands[1]));
1584 emit_insn (gen_movsi_botsym_s (operands[0], operands[0], operands[1]));
1585 return true;
1588 if (symbolref_p (operands[1])
1589 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1591 rtx temp;
1593 if (reload_in_progress || reload_completed)
1594 temp = operands[0];
1595 else
1596 temp = gen_reg_rtx (Pmode);
1598 emit_insn (gen_movsi_topsym_s (temp, operands[1]));
1599 emit_insn (gen_movsi_botsym_s (temp, temp, operands[1]));
1600 emit_move_insn (operands[0], replace_equiv_address (operands[1], temp));
1601 return true;
1604 return false;
1607 /* Cases where the pattern can't be made to use at all. */
1609 bool
1610 mep_mov_ok (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1612 int i;
1614 #define DEBUG_MOV_OK 0
1615 #if DEBUG_MOV_OK
1616 fprintf (stderr, "mep_mov_ok %s %c=%c\n", mode_name[mode], mep_section_tag (operands[0]),
1617 mep_section_tag (operands[1]));
1618 debug_rtx (operands[0]);
1619 debug_rtx (operands[1]);
1620 #endif
1622 /* We want the movh patterns to get these. */
1623 if (GET_CODE (operands[1]) == HIGH)
1624 return false;
1626 /* We can't store a register to a far variable without using a
1627 scratch register to hold the address. Using far variables should
1628 be split by mep_emit_mov anyway. */
1629 if (mep_section_tag (operands[0]) == 'f'
1630 || mep_section_tag (operands[1]) == 'f')
1632 #if DEBUG_MOV_OK
1633 fprintf (stderr, " - no, f\n");
1634 #endif
1635 return false;
1637 i = mep_section_tag (operands[1]);
1638 if ((i == 'b' || i == 't') && !reload_completed && !reload_in_progress)
1639 /* These are supposed to be generated with adds of the appropriate
1640 register. During and after reload, however, we allow them to
1641 be accessed as normal symbols because adding a dependency on
1642 the base register now might cause problems. */
1644 #if DEBUG_MOV_OK
1645 fprintf (stderr, " - no, bt\n");
1646 #endif
1647 return false;
1650 /* The only moves we can allow involve at least one general
1651 register, so require it. */
1652 for (i = 0; i < 2; i ++)
1654 /* Allow subregs too, before reload. */
1655 rtx x = operands[i];
1657 if (GET_CODE (x) == SUBREG)
1658 x = XEXP (x, 0);
1659 if (GET_CODE (x) == REG
1660 && ! MEP_CONTROL_REG (x))
1662 #if DEBUG_MOV_OK
1663 fprintf (stderr, " - ok\n");
1664 #endif
1665 return true;
1668 #if DEBUG_MOV_OK
1669 fprintf (stderr, " - no, no gen reg\n");
1670 #endif
1671 return false;
1674 #define DEBUG_SPLIT_WIDE_MOVE 0
1675 void
1676 mep_split_wide_move (rtx *operands, enum machine_mode mode)
1678 int i;
1680 #if DEBUG_SPLIT_WIDE_MOVE
1681 fprintf (stderr, "\n\033[34mmep_split_wide_move\033[0m mode %s\n", mode_name[mode]);
1682 debug_rtx (operands[0]);
1683 debug_rtx (operands[1]);
1684 #endif
1686 for (i = 0; i <= 1; i++)
1688 rtx op = operands[i], hi, lo;
1690 switch (GET_CODE (op))
1692 case REG:
1694 unsigned int regno = REGNO (op);
1696 if (TARGET_64BIT_CR_REGS && CR_REGNO_P (regno))
1698 rtx i32;
1700 lo = gen_rtx_REG (SImode, regno);
1701 i32 = GEN_INT (32);
1702 hi = gen_rtx_ZERO_EXTRACT (SImode,
1703 gen_rtx_REG (DImode, regno),
1704 i32, i32);
1706 else
1708 hi = gen_rtx_REG (SImode, regno + TARGET_LITTLE_ENDIAN);
1709 lo = gen_rtx_REG (SImode, regno + TARGET_BIG_ENDIAN);
1712 break;
1714 case CONST_INT:
1715 case CONST_DOUBLE:
1716 case MEM:
1717 hi = operand_subword (op, TARGET_LITTLE_ENDIAN, 0, mode);
1718 lo = operand_subword (op, TARGET_BIG_ENDIAN, 0, mode);
1719 break;
1721 default:
1722 gcc_unreachable ();
1725 /* The high part of CR <- GPR moves must be done after the low part. */
1726 operands [i + 4] = lo;
1727 operands [i + 2] = hi;
1730 if (reg_mentioned_p (operands[2], operands[5])
1731 || GET_CODE (operands[2]) == ZERO_EXTRACT
1732 || GET_CODE (operands[4]) == ZERO_EXTRACT)
1734 rtx tmp;
1736 /* Overlapping register pairs -- make sure we don't
1737 early-clobber ourselves. */
1738 tmp = operands[2];
1739 operands[2] = operands[4];
1740 operands[4] = tmp;
1741 tmp = operands[3];
1742 operands[3] = operands[5];
1743 operands[5] = tmp;
1746 #if DEBUG_SPLIT_WIDE_MOVE
1747 fprintf(stderr, "\033[34m");
1748 debug_rtx (operands[2]);
1749 debug_rtx (operands[3]);
1750 debug_rtx (operands[4]);
1751 debug_rtx (operands[5]);
1752 fprintf(stderr, "\033[0m");
1753 #endif
1756 /* Emit a setcc instruction in its entirity. */
1758 static bool
1759 mep_expand_setcc_1 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
1761 rtx tmp;
1763 switch (code)
1765 case GT:
1766 case GTU:
1767 tmp = op1, op1 = op2, op2 = tmp;
1768 code = swap_condition (code);
1769 /* FALLTHRU */
1771 case LT:
1772 case LTU:
1773 op1 = force_reg (SImode, op1);
1774 emit_insn (gen_rtx_SET (VOIDmode, dest,
1775 gen_rtx_fmt_ee (code, SImode, op1, op2)));
1776 return true;
1778 case EQ:
1779 if (op2 != const0_rtx)
1780 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1781 mep_expand_setcc_1 (LTU, dest, op1, const1_rtx);
1782 return true;
1784 case NE:
1785 /* Branchful sequence:
1786 mov dest, 0 16-bit
1787 beq op1, op2, Lover 16-bit (op2 < 16), 32-bit otherwise
1788 mov dest, 1 16-bit
1790 Branchless sequence:
1791 add3 tmp, op1, -op2 32-bit (or mov + sub)
1792 sltu3 tmp, tmp, 1 16-bit
1793 xor3 dest, tmp, 1 32-bit
1795 if (optimize_size && op2 != const0_rtx)
1796 return false;
1798 if (op2 != const0_rtx)
1799 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1801 op2 = gen_reg_rtx (SImode);
1802 mep_expand_setcc_1 (LTU, op2, op1, const1_rtx);
1804 emit_insn (gen_rtx_SET (VOIDmode, dest,
1805 gen_rtx_XOR (SImode, op2, const1_rtx)));
1806 return true;
1808 case LE:
1809 if (GET_CODE (op2) != CONST_INT
1810 || INTVAL (op2) == 0x7ffffff)
1811 return false;
1812 op2 = GEN_INT (INTVAL (op2) + 1);
1813 return mep_expand_setcc_1 (LT, dest, op1, op2);
1815 case LEU:
1816 if (GET_CODE (op2) != CONST_INT
1817 || INTVAL (op2) == -1)
1818 return false;
1819 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) + 1, SImode));
1820 return mep_expand_setcc_1 (LTU, dest, op1, op2);
1822 case GE:
1823 if (GET_CODE (op2) != CONST_INT
1824 || INTVAL (op2) == trunc_int_for_mode (0x80000000, SImode))
1825 return false;
1826 op2 = GEN_INT (INTVAL (op2) - 1);
1827 return mep_expand_setcc_1 (GT, dest, op1, op2);
1829 case GEU:
1830 if (GET_CODE (op2) != CONST_INT
1831 || op2 == const0_rtx)
1832 return false;
1833 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) - 1, SImode));
1834 return mep_expand_setcc_1 (GTU, dest, op1, op2);
1836 default:
1837 gcc_unreachable ();
1841 bool
1842 mep_expand_setcc (rtx *operands)
1844 rtx dest = operands[0];
1845 enum rtx_code code = GET_CODE (operands[1]);
1846 rtx op0 = operands[2];
1847 rtx op1 = operands[3];
1849 return mep_expand_setcc_1 (code, dest, op0, op1);
1853 mep_expand_cbranch (rtx *operands)
1855 enum rtx_code code = GET_CODE (operands[0]);
1856 rtx op0 = operands[1];
1857 rtx op1 = operands[2];
1858 rtx tmp;
1860 restart:
1861 switch (code)
1863 case LT:
1864 if (mep_imm4_operand (op1, SImode))
1865 break;
1867 tmp = gen_reg_rtx (SImode);
1868 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1869 code = NE;
1870 op0 = tmp;
1871 op1 = const0_rtx;
1872 break;
1874 case GE:
1875 if (mep_imm4_operand (op1, SImode))
1876 break;
1878 tmp = gen_reg_rtx (SImode);
1879 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1881 code = EQ;
1882 op0 = tmp;
1883 op1 = const0_rtx;
1884 break;
1886 case EQ:
1887 case NE:
1888 if (! mep_reg_or_imm4_operand (op1, SImode))
1889 op1 = force_reg (SImode, op1);
1890 break;
1892 case LE:
1893 case GT:
1894 if (GET_CODE (op1) == CONST_INT
1895 && INTVAL (op1) != 0x7fffffff)
1897 op1 = GEN_INT (INTVAL (op1) + 1);
1898 code = (code == LE ? LT : GE);
1899 goto restart;
1902 tmp = gen_reg_rtx (SImode);
1903 gcc_assert (mep_expand_setcc_1 (LT, tmp, op1, op0));
1905 code = (code == LE ? EQ : NE);
1906 op0 = tmp;
1907 op1 = const0_rtx;
1908 break;
1910 case LTU:
1911 if (op1 == const1_rtx)
1913 code = EQ;
1914 op1 = const0_rtx;
1915 break;
1918 tmp = gen_reg_rtx (SImode);
1919 gcc_assert (mep_expand_setcc_1 (LTU, tmp, op0, op1));
1920 code = NE;
1921 op0 = tmp;
1922 op1 = const0_rtx;
1923 break;
1925 case LEU:
1926 tmp = gen_reg_rtx (SImode);
1927 if (mep_expand_setcc_1 (LEU, tmp, op0, op1))
1928 code = NE;
1929 else if (mep_expand_setcc_1 (LTU, tmp, op1, op0))
1930 code = EQ;
1931 else
1932 gcc_unreachable ();
1933 op0 = tmp;
1934 op1 = const0_rtx;
1935 break;
1937 case GTU:
1938 tmp = gen_reg_rtx (SImode);
1939 gcc_assert (mep_expand_setcc_1 (GTU, tmp, op0, op1)
1940 || mep_expand_setcc_1 (LTU, tmp, op1, op0));
1941 code = NE;
1942 op0 = tmp;
1943 op1 = const0_rtx;
1944 break;
1946 case GEU:
1947 tmp = gen_reg_rtx (SImode);
1948 if (mep_expand_setcc_1 (GEU, tmp, op0, op1))
1949 code = NE;
1950 else if (mep_expand_setcc_1 (LTU, tmp, op0, op1))
1951 code = EQ;
1952 else
1953 gcc_unreachable ();
1954 op0 = tmp;
1955 op1 = const0_rtx;
1956 break;
1958 default:
1959 gcc_unreachable ();
1962 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1965 const char *
1966 mep_emit_cbranch (rtx *operands, int ne)
1968 if (GET_CODE (operands[1]) == REG)
1969 return ne ? "bne\t%0, %1, %l2" : "beq\t%0, %1, %l2";
1970 else if (INTVAL (operands[1]) == 0 && !mep_vliw_function_p(cfun->decl))
1971 return ne ? "bnez\t%0, %l2" : "beqz\t%0, %l2";
1972 else
1973 return ne ? "bnei\t%0, %1, %l2" : "beqi\t%0, %1, %l2";
1976 void
1977 mep_expand_call (rtx *operands, int returns_value)
1979 rtx addr = operands[returns_value];
1980 rtx tp = mep_tp_rtx ();
1981 rtx gp = mep_gp_rtx ();
1983 gcc_assert (GET_CODE (addr) == MEM);
1985 addr = XEXP (addr, 0);
1987 if (! mep_call_address_operand (addr, VOIDmode))
1988 addr = force_reg (SImode, addr);
1990 if (! operands[returns_value+2])
1991 operands[returns_value+2] = const0_rtx;
1993 if (returns_value)
1994 emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
1995 operands[3], tp, gp));
1996 else
1997 emit_call_insn (gen_call_internal (addr, operands[1],
1998 operands[2], tp, gp));
2001 /* Aliasing Support. */
2003 /* If X is a machine specific address (i.e. a symbol or label being
2004 referenced as a displacement from the GOT implemented using an
2005 UNSPEC), then return the base term. Otherwise return X. */
2008 mep_find_base_term (rtx x)
2010 rtx base, term;
2011 int unspec;
2013 if (GET_CODE (x) != PLUS)
2014 return x;
2015 base = XEXP (x, 0);
2016 term = XEXP (x, 1);
2018 if (has_hard_reg_initial_val(Pmode, TP_REGNO)
2019 && base == mep_tp_rtx ())
2020 unspec = UNS_TPREL;
2021 else if (has_hard_reg_initial_val(Pmode, GP_REGNO)
2022 && base == mep_gp_rtx ())
2023 unspec = UNS_GPREL;
2024 else
2025 return x;
2027 if (GET_CODE (term) != CONST)
2028 return x;
2029 term = XEXP (term, 0);
2031 if (GET_CODE (term) != UNSPEC
2032 || XINT (term, 1) != unspec)
2033 return x;
2035 return XVECEXP (term, 0, 0);
2038 /* Reload Support. */
2040 /* Return true if the registers in CLASS cannot represent the change from
2041 modes FROM to TO. */
2043 bool
2044 mep_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
2045 enum reg_class regclass)
2047 if (from == to)
2048 return false;
2050 /* 64-bit COP regs must remain 64-bit COP regs. */
2051 if (TARGET_64BIT_CR_REGS
2052 && (regclass == CR_REGS
2053 || regclass == LOADABLE_CR_REGS)
2054 && (GET_MODE_SIZE (to) < 8
2055 || GET_MODE_SIZE (from) < 8))
2056 return true;
2058 return false;
2061 #define MEP_NONGENERAL_CLASS(C) (!reg_class_subset_p (C, GENERAL_REGS))
2063 static bool
2064 mep_general_reg (rtx x)
2066 while (GET_CODE (x) == SUBREG)
2067 x = XEXP (x, 0);
2068 return GET_CODE (x) == REG && GR_REGNO_P (REGNO (x));
2071 static bool
2072 mep_nongeneral_reg (rtx x)
2074 while (GET_CODE (x) == SUBREG)
2075 x = XEXP (x, 0);
2076 return (GET_CODE (x) == REG
2077 && !GR_REGNO_P (REGNO (x)) && REGNO (x) < FIRST_PSEUDO_REGISTER);
2080 static bool
2081 mep_general_copro_reg (rtx x)
2083 while (GET_CODE (x) == SUBREG)
2084 x = XEXP (x, 0);
2085 return (GET_CODE (x) == REG && CR_REGNO_P (REGNO (x)));
2088 static bool
2089 mep_nonregister (rtx x)
2091 while (GET_CODE (x) == SUBREG)
2092 x = XEXP (x, 0);
2093 return (GET_CODE (x) != REG || REGNO (x) >= FIRST_PSEUDO_REGISTER);
2096 #define DEBUG_RELOAD 0
2098 /* Return the secondary reload class needed for moving value X to or
2099 from a register in coprocessor register class CLASS. */
2101 static enum reg_class
2102 mep_secondary_copro_reload_class (enum reg_class rclass, rtx x)
2104 if (mep_general_reg (x))
2105 /* We can do the move directly if mep_have_core_copro_moves_p,
2106 otherwise we need to go through memory. Either way, no secondary
2107 register is needed. */
2108 return NO_REGS;
2110 if (mep_general_copro_reg (x))
2112 /* We can do the move directly if mep_have_copro_copro_moves_p. */
2113 if (mep_have_copro_copro_moves_p)
2114 return NO_REGS;
2116 /* Otherwise we can use a temporary if mep_have_core_copro_moves_p. */
2117 if (mep_have_core_copro_moves_p)
2118 return GENERAL_REGS;
2120 /* Otherwise we need to do it through memory. No secondary
2121 register is needed. */
2122 return NO_REGS;
2125 if (reg_class_subset_p (rclass, LOADABLE_CR_REGS)
2126 && constraint_satisfied_p (x, CONSTRAINT_U))
2127 /* X is a memory value that we can access directly. */
2128 return NO_REGS;
2130 /* We have to move X into a GPR first and then copy it to
2131 the coprocessor register. The move from the GPR to the
2132 coprocessor might be done directly or through memory,
2133 depending on mep_have_core_copro_moves_p. */
2134 return GENERAL_REGS;
2137 /* Copying X to register in RCLASS. */
2139 enum reg_class
2140 mep_secondary_input_reload_class (enum reg_class rclass,
2141 enum machine_mode mode ATTRIBUTE_UNUSED,
2142 rtx x)
2144 int rv = NO_REGS;
2146 #if DEBUG_RELOAD
2147 fprintf (stderr, "secondary input reload copy to %s %s from ", reg_class_names[rclass], mode_name[mode]);
2148 debug_rtx (x);
2149 #endif
2151 if (reg_class_subset_p (rclass, CR_REGS))
2152 rv = mep_secondary_copro_reload_class (rclass, x);
2153 else if (MEP_NONGENERAL_CLASS (rclass)
2154 && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2155 rv = GENERAL_REGS;
2157 #if DEBUG_RELOAD
2158 fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2159 #endif
2160 return (enum reg_class) rv;
2163 /* Copying register in RCLASS to X. */
2165 enum reg_class
2166 mep_secondary_output_reload_class (enum reg_class rclass,
2167 enum machine_mode mode ATTRIBUTE_UNUSED,
2168 rtx x)
2170 int rv = NO_REGS;
2172 #if DEBUG_RELOAD
2173 fprintf (stderr, "secondary output reload copy from %s %s to ", reg_class_names[rclass], mode_name[mode]);
2174 debug_rtx (x);
2175 #endif
2177 if (reg_class_subset_p (rclass, CR_REGS))
2178 rv = mep_secondary_copro_reload_class (rclass, x);
2179 else if (MEP_NONGENERAL_CLASS (rclass)
2180 && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2181 rv = GENERAL_REGS;
2183 #if DEBUG_RELOAD
2184 fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2185 #endif
2187 return (enum reg_class) rv;
2190 /* Implement SECONDARY_MEMORY_NEEDED. */
2192 bool
2193 mep_secondary_memory_needed (enum reg_class rclass1, enum reg_class rclass2,
2194 enum machine_mode mode ATTRIBUTE_UNUSED)
2196 if (!mep_have_core_copro_moves_p)
2198 if (reg_classes_intersect_p (rclass1, CR_REGS)
2199 && reg_classes_intersect_p (rclass2, GENERAL_REGS))
2200 return true;
2201 if (reg_classes_intersect_p (rclass2, CR_REGS)
2202 && reg_classes_intersect_p (rclass1, GENERAL_REGS))
2203 return true;
2204 if (!mep_have_copro_copro_moves_p
2205 && reg_classes_intersect_p (rclass1, CR_REGS)
2206 && reg_classes_intersect_p (rclass2, CR_REGS))
2207 return true;
2209 return false;
2212 void
2213 mep_expand_reload (rtx *operands, enum machine_mode mode)
2215 /* There are three cases for each direction:
2216 register, farsym
2217 control, farsym
2218 control, nearsym */
2220 int s0 = mep_section_tag (operands[0]) == 'f';
2221 int s1 = mep_section_tag (operands[1]) == 'f';
2222 int c0 = mep_nongeneral_reg (operands[0]);
2223 int c1 = mep_nongeneral_reg (operands[1]);
2224 int which = (s0 ? 20:0) + (c0 ? 10:0) + (s1 ? 2:0) + (c1 ? 1:0);
2226 #if DEBUG_RELOAD
2227 fprintf (stderr, "expand_reload %s\n", mode_name[mode]);
2228 debug_rtx (operands[0]);
2229 debug_rtx (operands[1]);
2230 #endif
2232 switch (which)
2234 case 00: /* Don't know why this gets here. */
2235 case 02: /* general = far */
2236 emit_move_insn (operands[0], operands[1]);
2237 return;
2239 case 10: /* cr = mem */
2240 case 11: /* cr = cr */
2241 case 01: /* mem = cr */
2242 case 12: /* cr = far */
2243 emit_move_insn (operands[2], operands[1]);
2244 emit_move_insn (operands[0], operands[2]);
2245 return;
2247 case 20: /* far = general */
2248 emit_move_insn (operands[2], XEXP (operands[1], 0));
2249 emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2]));
2250 return;
2252 case 21: /* far = cr */
2253 case 22: /* far = far */
2254 default:
2255 fprintf (stderr, "unsupported expand reload case %02d for mode %s\n",
2256 which, mode_name[mode]);
2257 debug_rtx (operands[0]);
2258 debug_rtx (operands[1]);
2259 gcc_unreachable ();
2263 /* Implement PREFERRED_RELOAD_CLASS. See whether X is a constant that
2264 can be moved directly into registers 0 to 7, but not into the rest.
2265 If so, and if the required class includes registers 0 to 7, restrict
2266 it to those registers. */
2268 enum reg_class
2269 mep_preferred_reload_class (rtx x, enum reg_class rclass)
2271 switch (GET_CODE (x))
2273 case CONST_INT:
2274 if (INTVAL (x) >= 0x10000
2275 && INTVAL (x) < 0x01000000
2276 && (INTVAL (x) & 0xffff) != 0
2277 && reg_class_subset_p (TPREL_REGS, rclass))
2278 rclass = TPREL_REGS;
2279 break;
2281 case CONST:
2282 case SYMBOL_REF:
2283 case LABEL_REF:
2284 if (mep_section_tag (x) != 'f'
2285 && reg_class_subset_p (TPREL_REGS, rclass))
2286 rclass = TPREL_REGS;
2287 break;
2289 default:
2290 break;
2292 return rclass;
2295 /* Implement REGISTER_MOVE_COST. Return 2 for direct single-register
2296 moves, 4 for direct double-register moves, and 1000 for anything
2297 that requires a temporary register or temporary stack slot. */
2300 mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_class to)
2302 if (mep_have_copro_copro_moves_p
2303 && reg_class_subset_p (from, CR_REGS)
2304 && reg_class_subset_p (to, CR_REGS))
2306 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2307 return 4;
2308 return 2;
2310 if (reg_class_subset_p (from, CR_REGS)
2311 && reg_class_subset_p (to, CR_REGS))
2313 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2314 return 8;
2315 return 4;
2317 if (reg_class_subset_p (from, CR_REGS)
2318 || reg_class_subset_p (to, CR_REGS))
2320 if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2321 return 4;
2322 return 2;
2324 if (mep_secondary_memory_needed (from, to, mode))
2325 return 1000;
2326 if (MEP_NONGENERAL_CLASS (from) && MEP_NONGENERAL_CLASS (to))
2327 return 1000;
2329 if (GET_MODE_SIZE (mode) > 4)
2330 return 4;
2332 return 2;
2336 /* Functions to save and restore machine-specific function data. */
2338 static struct machine_function *
2339 mep_init_machine_status (void)
2341 return ggc_alloc_cleared_machine_function ();
2344 static rtx
2345 mep_allocate_initial_value (rtx reg)
2347 int rss;
2349 if (GET_CODE (reg) != REG)
2350 return NULL_RTX;
2352 if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
2353 return NULL_RTX;
2355 /* In interrupt functions, the "initial" values of $gp and $tp are
2356 provided by the prologue. They are not necessarily the same as
2357 the values that the caller was using. */
2358 if (REGNO (reg) == TP_REGNO || REGNO (reg) == GP_REGNO)
2359 if (mep_interrupt_p ())
2360 return NULL_RTX;
2362 if (! cfun->machine->reg_save_slot[REGNO(reg)])
2364 cfun->machine->reg_save_size += 4;
2365 cfun->machine->reg_save_slot[REGNO(reg)] = cfun->machine->reg_save_size;
2368 rss = cfun->machine->reg_save_slot[REGNO(reg)];
2369 return gen_rtx_MEM (SImode, plus_constant (arg_pointer_rtx, -rss));
2373 mep_return_addr_rtx (int count)
2375 if (count != 0)
2376 return const0_rtx;
2378 return get_hard_reg_initial_val (Pmode, LP_REGNO);
2381 static rtx
2382 mep_tp_rtx (void)
2384 return get_hard_reg_initial_val (Pmode, TP_REGNO);
2387 static rtx
2388 mep_gp_rtx (void)
2390 return get_hard_reg_initial_val (Pmode, GP_REGNO);
2393 static bool
2394 mep_interrupt_p (void)
2396 if (cfun->machine->interrupt_handler == 0)
2398 int interrupt_handler
2399 = (lookup_attribute ("interrupt",
2400 DECL_ATTRIBUTES (current_function_decl))
2401 != NULL_TREE);
2402 cfun->machine->interrupt_handler = interrupt_handler ? 2 : 1;
2404 return cfun->machine->interrupt_handler == 2;
2407 static bool
2408 mep_disinterrupt_p (void)
2410 if (cfun->machine->disable_interrupts == 0)
2412 int disable_interrupts
2413 = (lookup_attribute ("disinterrupt",
2414 DECL_ATTRIBUTES (current_function_decl))
2415 != NULL_TREE);
2416 cfun->machine->disable_interrupts = disable_interrupts ? 2 : 1;
2418 return cfun->machine->disable_interrupts == 2;
2422 /* Frame/Epilog/Prolog Related. */
2424 static bool
2425 mep_reg_set_p (rtx reg, rtx insn)
2427 /* Similar to reg_set_p in rtlanal.c, but we ignore calls */
2428 if (INSN_P (insn))
2430 if (FIND_REG_INC_NOTE (insn, reg))
2431 return true;
2432 insn = PATTERN (insn);
2435 if (GET_CODE (insn) == SET
2436 && GET_CODE (XEXP (insn, 0)) == REG
2437 && GET_CODE (XEXP (insn, 1)) == REG
2438 && REGNO (XEXP (insn, 0)) == REGNO (XEXP (insn, 1)))
2439 return false;
2441 return set_of (reg, insn) != NULL_RTX;
2445 #define MEP_SAVES_UNKNOWN 0
2446 #define MEP_SAVES_YES 1
2447 #define MEP_SAVES_MAYBE 2
2448 #define MEP_SAVES_NO 3
2450 static bool
2451 mep_reg_set_in_function (int regno)
2453 rtx reg, insn;
2455 if (mep_interrupt_p () && df_regs_ever_live_p(regno))
2456 return true;
2458 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2459 return true;
2461 push_topmost_sequence ();
2462 insn = get_insns ();
2463 pop_topmost_sequence ();
2465 if (!insn)
2466 return false;
2468 reg = gen_rtx_REG (SImode, regno);
2470 for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
2471 if (INSN_P (insn) && mep_reg_set_p (reg, insn))
2472 return true;
2473 return false;
2476 static bool
2477 mep_asm_without_operands_p (void)
2479 if (cfun->machine->asms_without_operands == 0)
2481 rtx insn;
2483 push_topmost_sequence ();
2484 insn = get_insns ();
2485 pop_topmost_sequence ();
2487 cfun->machine->asms_without_operands = 1;
2488 while (insn)
2490 if (INSN_P (insn)
2491 && GET_CODE (PATTERN (insn)) == ASM_INPUT)
2493 cfun->machine->asms_without_operands = 2;
2494 break;
2496 insn = NEXT_INSN (insn);
2500 return cfun->machine->asms_without_operands == 2;
2503 /* Interrupt functions save/restore every call-preserved register, and
2504 any call-used register it uses (or all if it calls any function,
2505 since they may get clobbered there too). Here we check to see
2506 which call-used registers need saving. */
2508 #define IVC2_ISAVED_REG(r) (TARGET_IVC2 \
2509 && (r == FIRST_CCR_REGNO + 1 \
2510 || (r >= FIRST_CCR_REGNO + 8 && r <= FIRST_CCR_REGNO + 11) \
2511 || (r >= FIRST_CCR_REGNO + 16 && r <= FIRST_CCR_REGNO + 31)))
2513 static bool
2514 mep_interrupt_saved_reg (int r)
2516 if (!mep_interrupt_p ())
2517 return false;
2518 if (r == REGSAVE_CONTROL_TEMP
2519 || (TARGET_64BIT_CR_REGS && TARGET_COP && r == REGSAVE_CONTROL_TEMP+1))
2520 return true;
2521 if (mep_asm_without_operands_p ()
2522 && (!fixed_regs[r]
2523 || (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO || r == LP_REGNO)
2524 || IVC2_ISAVED_REG (r)))
2525 return true;
2526 if (!current_function_is_leaf)
2527 /* Function calls mean we need to save $lp. */
2528 if (r == LP_REGNO || IVC2_ISAVED_REG (r))
2529 return true;
2530 if (!current_function_is_leaf || cfun->machine->doloop_tags > 0)
2531 /* The interrupt handler might use these registers for repeat blocks,
2532 or it might call a function that does so. */
2533 if (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO)
2534 return true;
2535 if (current_function_is_leaf && call_used_regs[r] && !df_regs_ever_live_p(r))
2536 return false;
2537 /* Functions we call might clobber these. */
2538 if (call_used_regs[r] && !fixed_regs[r])
2539 return true;
2540 /* Additional registers that need to be saved for IVC2. */
2541 if (IVC2_ISAVED_REG (r))
2542 return true;
2544 return false;
2547 static bool
2548 mep_call_saves_register (int r)
2550 if (! cfun->machine->frame_locked)
2552 int rv = MEP_SAVES_NO;
2554 if (cfun->machine->reg_save_slot[r])
2555 rv = MEP_SAVES_YES;
2556 else if (r == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2557 rv = MEP_SAVES_YES;
2558 else if (r == FRAME_POINTER_REGNUM && frame_pointer_needed)
2559 rv = MEP_SAVES_YES;
2560 else if ((!call_used_regs[r] || r == LP_REGNO) && df_regs_ever_live_p(r))
2561 rv = MEP_SAVES_YES;
2562 else if (crtl->calls_eh_return && (r == 10 || r == 11))
2563 /* We need these to have stack slots so that they can be set during
2564 unwinding. */
2565 rv = MEP_SAVES_YES;
2566 else if (mep_interrupt_saved_reg (r))
2567 rv = MEP_SAVES_YES;
2568 cfun->machine->reg_saved[r] = rv;
2570 return cfun->machine->reg_saved[r] == MEP_SAVES_YES;
2573 /* Return true if epilogue uses register REGNO. */
2575 bool
2576 mep_epilogue_uses (int regno)
2578 /* Since $lp is a call-saved register, the generic code will normally
2579 mark it used in the epilogue if it needs to be saved and restored.
2580 However, when profiling is enabled, the profiling code will implicitly
2581 clobber $11. This case has to be handled specially both here and in
2582 mep_call_saves_register. */
2583 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2584 return true;
2585 /* Interrupt functions save/restore pretty much everything. */
2586 return (reload_completed && mep_interrupt_saved_reg (regno));
2589 static int
2590 mep_reg_size (int regno)
2592 if (CR_REGNO_P (regno) && TARGET_64BIT_CR_REGS)
2593 return 8;
2594 return 4;
2597 /* Worker function for TARGET_CAN_ELIMINATE. */
2599 bool
2600 mep_can_eliminate (const int from, const int to)
2602 return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
2603 ? ! frame_pointer_needed
2604 : true);
2608 mep_elimination_offset (int from, int to)
2610 int reg_save_size;
2611 int i;
2612 int frame_size = get_frame_size () + crtl->outgoing_args_size;
2613 int total_size;
2615 if (!cfun->machine->frame_locked)
2616 memset (cfun->machine->reg_saved, 0, sizeof (cfun->machine->reg_saved));
2618 /* We don't count arg_regs_to_save in the arg pointer offset, because
2619 gcc thinks the arg pointer has moved along with the saved regs.
2620 However, we do count it when we adjust $sp in the prologue. */
2621 reg_save_size = 0;
2622 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2623 if (mep_call_saves_register (i))
2624 reg_save_size += mep_reg_size (i);
2626 if (reg_save_size % 8)
2627 cfun->machine->regsave_filler = 8 - (reg_save_size % 8);
2628 else
2629 cfun->machine->regsave_filler = 0;
2631 /* This is what our total stack adjustment looks like. */
2632 total_size = (reg_save_size + frame_size + cfun->machine->regsave_filler);
2634 if (total_size % 8)
2635 cfun->machine->frame_filler = 8 - (total_size % 8);
2636 else
2637 cfun->machine->frame_filler = 0;
2640 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2641 return reg_save_size + cfun->machine->regsave_filler;
2643 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2644 return cfun->machine->frame_filler + frame_size;
2646 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2647 return reg_save_size + cfun->machine->regsave_filler + cfun->machine->frame_filler + frame_size;
2649 gcc_unreachable ();
2652 static rtx
2653 F (rtx x)
2655 RTX_FRAME_RELATED_P (x) = 1;
2656 return x;
2659 /* Since the prologue/epilogue code is generated after optimization,
2660 we can't rely on gcc to split constants for us. So, this code
2661 captures all the ways to add a constant to a register in one logic
2662 chunk, including optimizing away insns we just don't need. This
2663 makes the prolog/epilog code easier to follow. */
2664 static void
2665 add_constant (int dest, int src, int value, int mark_frame)
2667 rtx insn;
2668 int hi, lo;
2670 if (src == dest && value == 0)
2671 return;
2673 if (value == 0)
2675 insn = emit_move_insn (gen_rtx_REG (SImode, dest),
2676 gen_rtx_REG (SImode, src));
2677 if (mark_frame)
2678 RTX_FRAME_RELATED_P(insn) = 1;
2679 return;
2682 if (value >= -32768 && value <= 32767)
2684 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2685 gen_rtx_REG (SImode, src),
2686 GEN_INT (value)));
2687 if (mark_frame)
2688 RTX_FRAME_RELATED_P(insn) = 1;
2689 return;
2692 /* Big constant, need to use a temp register. We use
2693 REGSAVE_CONTROL_TEMP because it's call clobberable (the reg save
2694 area is always small enough to directly add to). */
2696 hi = trunc_int_for_mode (value & 0xffff0000, SImode);
2697 lo = value & 0xffff;
2699 insn = emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2700 GEN_INT (hi));
2702 if (lo)
2704 insn = emit_insn (gen_iorsi3 (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2705 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2706 GEN_INT (lo)));
2709 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2710 gen_rtx_REG (SImode, src),
2711 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP)));
2712 if (mark_frame)
2714 RTX_FRAME_RELATED_P(insn) = 1;
2715 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2716 gen_rtx_SET (SImode,
2717 gen_rtx_REG (SImode, dest),
2718 gen_rtx_PLUS (SImode,
2719 gen_rtx_REG (SImode, dest),
2720 GEN_INT (value))));
2724 /* Move SRC to DEST. Mark the move as being potentially dead if
2725 MAYBE_DEAD_P. */
2727 static rtx
2728 maybe_dead_move (rtx dest, rtx src, bool ATTRIBUTE_UNUSED maybe_dead_p)
2730 rtx insn = emit_move_insn (dest, src);
2731 #if 0
2732 if (maybe_dead_p)
2733 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
2734 #endif
2735 return insn;
2738 /* Used for interrupt functions, which can't assume that $tp and $gp
2739 contain the correct pointers. */
2741 static void
2742 mep_reload_pointer (int regno, const char *symbol)
2744 rtx reg, sym;
2746 if (!df_regs_ever_live_p(regno) && current_function_is_leaf)
2747 return;
2749 reg = gen_rtx_REG (SImode, regno);
2750 sym = gen_rtx_SYMBOL_REF (SImode, symbol);
2751 emit_insn (gen_movsi_topsym_s (reg, sym));
2752 emit_insn (gen_movsi_botsym_s (reg, reg, sym));
2755 /* Assign save slots for any register not already saved. DImode
2756 registers go at the end of the reg save area; the rest go at the
2757 beginning. This is for alignment purposes. Returns true if a frame
2758 is really needed. */
2759 static bool
2760 mep_assign_save_slots (int reg_save_size)
2762 bool really_need_stack_frame = false;
2763 int di_ofs = 0;
2764 int i;
2766 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2767 if (mep_call_saves_register(i))
2769 int regsize = mep_reg_size (i);
2771 if ((i != TP_REGNO && i != GP_REGNO && i != LP_REGNO)
2772 || mep_reg_set_in_function (i))
2773 really_need_stack_frame = true;
2775 if (cfun->machine->reg_save_slot[i])
2776 continue;
2778 if (regsize < 8)
2780 cfun->machine->reg_save_size += regsize;
2781 cfun->machine->reg_save_slot[i] = cfun->machine->reg_save_size;
2783 else
2785 cfun->machine->reg_save_slot[i] = reg_save_size - di_ofs;
2786 di_ofs += 8;
2789 cfun->machine->frame_locked = 1;
2790 return really_need_stack_frame;
2793 void
2794 mep_expand_prologue (void)
2796 int i, rss, sp_offset = 0;
2797 int reg_save_size;
2798 int frame_size;
2799 int really_need_stack_frame;
2801 /* We must not allow register renaming in interrupt functions,
2802 because that invalidates the correctness of the set of call-used
2803 registers we're going to save/restore. */
2804 mep_set_leaf_registers (mep_interrupt_p () ? 0 : 1);
2806 if (mep_disinterrupt_p ())
2807 emit_insn (gen_mep_disable_int ());
2809 cfun->machine->mep_frame_pointer_needed = frame_pointer_needed;
2811 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2812 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2813 really_need_stack_frame = frame_size;
2815 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2817 sp_offset = reg_save_size;
2818 if (sp_offset + frame_size < 128)
2819 sp_offset += frame_size ;
2821 add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2823 for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2824 if (mep_call_saves_register(i))
2826 rtx mem;
2827 bool maybe_dead_p;
2828 enum machine_mode rmode;
2830 rss = cfun->machine->reg_save_slot[i];
2832 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2833 && (!mep_reg_set_in_function (i)
2834 && !mep_interrupt_p ()))
2835 continue;
2837 if (mep_reg_size (i) == 8)
2838 rmode = DImode;
2839 else
2840 rmode = SImode;
2842 /* If there is a pseudo associated with this register's initial value,
2843 reload might have already spilt it to the stack slot suggested by
2844 ALLOCATE_INITIAL_VALUE. The moves emitted here can then be safely
2845 deleted as dead. */
2846 mem = gen_rtx_MEM (rmode,
2847 plus_constant (stack_pointer_rtx, sp_offset - rss));
2848 maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2850 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2851 F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2852 else if (rmode == DImode)
2854 rtx insn;
2855 int be = TARGET_BIG_ENDIAN ? 4 : 0;
2857 mem = gen_rtx_MEM (SImode,
2858 plus_constant (stack_pointer_rtx, sp_offset - rss + be));
2860 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2861 gen_rtx_REG (SImode, i),
2862 maybe_dead_p);
2863 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2864 gen_rtx_ZERO_EXTRACT (SImode,
2865 gen_rtx_REG (DImode, i),
2866 GEN_INT (32),
2867 GEN_INT (32)),
2868 maybe_dead_p);
2869 insn = maybe_dead_move (mem,
2870 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2871 maybe_dead_p);
2872 RTX_FRAME_RELATED_P (insn) = 1;
2874 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2875 gen_rtx_SET (VOIDmode,
2876 copy_rtx (mem),
2877 gen_rtx_REG (rmode, i)));
2878 mem = gen_rtx_MEM (SImode,
2879 plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be)));
2880 insn = maybe_dead_move (mem,
2881 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2882 maybe_dead_p);
2884 else
2886 rtx insn;
2887 maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2888 gen_rtx_REG (rmode, i),
2889 maybe_dead_p);
2890 insn = maybe_dead_move (mem,
2891 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2892 maybe_dead_p);
2893 RTX_FRAME_RELATED_P (insn) = 1;
2895 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2896 gen_rtx_SET (VOIDmode,
2897 copy_rtx (mem),
2898 gen_rtx_REG (rmode, i)));
2902 if (frame_pointer_needed)
2904 /* We've already adjusted down by sp_offset. Total $sp change
2905 is reg_save_size + frame_size. We want a net change here of
2906 just reg_save_size. */
2907 add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2910 add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2912 if (mep_interrupt_p ())
2914 mep_reload_pointer(GP_REGNO, "__sdabase");
2915 mep_reload_pointer(TP_REGNO, "__tpbase");
2919 static void
2920 mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2922 int local = hwi_local;
2923 int frame_size = local + crtl->outgoing_args_size;
2924 int reg_save_size;
2925 int ffill;
2926 int i, sp, skip;
2927 int sp_offset;
2928 int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2930 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2931 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2932 sp_offset = reg_save_size + frame_size;
2934 ffill = cfun->machine->frame_filler;
2936 if (cfun->machine->mep_frame_pointer_needed)
2937 reg_names[FP_REGNO] = "$fp";
2938 else
2939 reg_names[FP_REGNO] = "$8";
2941 if (sp_offset == 0)
2942 return;
2944 if (debug_info_level == DINFO_LEVEL_NONE)
2946 fprintf (file, "\t# frame: %d", sp_offset);
2947 if (reg_save_size)
2948 fprintf (file, " %d regs", reg_save_size);
2949 if (local)
2950 fprintf (file, " %d locals", local);
2951 if (crtl->outgoing_args_size)
2952 fprintf (file, " %d args", crtl->outgoing_args_size);
2953 fprintf (file, "\n");
2954 return;
2957 fprintf (file, "\t#\n");
2958 fprintf (file, "\t# Initial Frame Information:\n");
2959 if (sp_offset || !frame_pointer_needed)
2960 fprintf (file, "\t# Entry ---------- 0\n");
2962 /* Sort registers by save slots, so they're printed in the order
2963 they appear in memory, not the order they're saved in. */
2964 for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
2965 slot_map[si] = si;
2966 for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
2967 for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
2968 if (cfun->machine->reg_save_slot[slot_map[si]]
2969 > cfun->machine->reg_save_slot[slot_map[sj]])
2971 int t = slot_map[si];
2972 slot_map[si] = slot_map[sj];
2973 slot_map[sj] = t;
2976 sp = 0;
2977 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2979 int rsize;
2980 int r = slot_map[i];
2981 int rss = cfun->machine->reg_save_slot[r];
2983 if (!mep_call_saves_register (r))
2984 continue;
2986 if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
2987 && (!mep_reg_set_in_function (r)
2988 && !mep_interrupt_p ()))
2989 continue;
2991 rsize = mep_reg_size(r);
2992 skip = rss - (sp+rsize);
2993 if (skip)
2994 fprintf (file, "\t# %3d bytes for alignment\n", skip);
2995 fprintf (file, "\t# %3d bytes for saved %-3s %3d($sp)\n",
2996 rsize, reg_names[r], sp_offset - rss);
2997 sp = rss;
3000 skip = reg_save_size - sp;
3001 if (skip)
3002 fprintf (file, "\t# %3d bytes for alignment\n", skip);
3004 if (frame_pointer_needed)
3005 fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
3006 if (local)
3007 fprintf (file, "\t# %3d bytes for local vars\n", local);
3008 if (ffill)
3009 fprintf (file, "\t# %3d bytes for alignment\n", ffill);
3010 if (crtl->outgoing_args_size)
3011 fprintf (file, "\t# %3d bytes for outgoing args\n",
3012 crtl->outgoing_args_size);
3013 fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
3014 fprintf (file, "\t#\n");
3018 static int mep_prevent_lp_restore = 0;
3019 static int mep_sibcall_epilogue = 0;
3021 void
3022 mep_expand_epilogue (void)
3024 int i, sp_offset = 0;
3025 int reg_save_size = 0;
3026 int frame_size;
3027 int lp_temp = LP_REGNO, lp_slot = -1;
3028 int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
3029 int interrupt_handler = mep_interrupt_p ();
3031 if (profile_arc_flag == 2)
3032 emit_insn (gen_mep_bb_trace_ret ());
3034 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
3035 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
3037 really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
3039 if (frame_pointer_needed)
3041 /* If we have a frame pointer, we won't have a reliable stack
3042 pointer (alloca, you know), so rebase SP from FP */
3043 emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
3044 gen_rtx_REG (SImode, FP_REGNO));
3045 sp_offset = reg_save_size;
3047 else
3049 /* SP is right under our local variable space. Adjust it if
3050 needed. */
3051 sp_offset = reg_save_size + frame_size;
3052 if (sp_offset >= 128)
3054 add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
3055 sp_offset -= frame_size;
3059 /* This is backwards so that we restore the control and coprocessor
3060 registers before the temporary registers we use to restore
3061 them. */
3062 for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
3063 if (mep_call_saves_register (i))
3065 enum machine_mode rmode;
3066 int rss = cfun->machine->reg_save_slot[i];
3068 if (mep_reg_size (i) == 8)
3069 rmode = DImode;
3070 else
3071 rmode = SImode;
3073 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
3074 && !(mep_reg_set_in_function (i) || interrupt_handler))
3075 continue;
3076 if (mep_prevent_lp_restore && i == LP_REGNO)
3077 continue;
3078 if (!mep_prevent_lp_restore
3079 && !interrupt_handler
3080 && (i == 10 || i == 11))
3081 continue;
3083 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
3084 emit_move_insn (gen_rtx_REG (rmode, i),
3085 gen_rtx_MEM (rmode,
3086 plus_constant (stack_pointer_rtx,
3087 sp_offset-rss)));
3088 else
3090 if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
3091 /* Defer this one so we can jump indirect rather than
3092 copying the RA to $lp and "ret". EH epilogues
3093 automatically skip this anyway. */
3094 lp_slot = sp_offset-rss;
3095 else
3097 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
3098 gen_rtx_MEM (rmode,
3099 plus_constant (stack_pointer_rtx,
3100 sp_offset-rss)));
3101 emit_move_insn (gen_rtx_REG (rmode, i),
3102 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
3106 if (lp_slot != -1)
3108 /* Restore this one last so we know it will be in the temp
3109 register when we return by jumping indirectly via the temp. */
3110 emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
3111 gen_rtx_MEM (SImode,
3112 plus_constant (stack_pointer_rtx,
3113 lp_slot)));
3114 lp_temp = REGSAVE_CONTROL_TEMP;
3118 add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
3120 if (crtl->calls_eh_return && mep_prevent_lp_restore)
3121 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3122 gen_rtx_REG (SImode, SP_REGNO),
3123 cfun->machine->eh_stack_adjust));
3125 if (mep_sibcall_epilogue)
3126 return;
3128 if (mep_disinterrupt_p ())
3129 emit_insn (gen_mep_enable_int ());
3131 if (mep_prevent_lp_restore)
3133 emit_jump_insn (gen_eh_return_internal ());
3134 emit_barrier ();
3136 else if (interrupt_handler)
3137 emit_jump_insn (gen_mep_reti ());
3138 else
3139 emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3142 void
3143 mep_expand_eh_return (rtx *operands)
3145 if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3147 rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3148 emit_move_insn (ra, operands[0]);
3149 operands[0] = ra;
3152 emit_insn (gen_eh_epilogue (operands[0]));
3155 void
3156 mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3158 cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3159 mep_prevent_lp_restore = 1;
3160 mep_expand_epilogue ();
3161 mep_prevent_lp_restore = 0;
3164 void
3165 mep_expand_sibcall_epilogue (void)
3167 mep_sibcall_epilogue = 1;
3168 mep_expand_epilogue ();
3169 mep_sibcall_epilogue = 0;
3172 static bool
3173 mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3175 if (decl == NULL)
3176 return false;
3178 if (mep_section_tag (DECL_RTL (decl)) == 'f')
3179 return false;
3181 /* Can't call to a sibcall from an interrupt or disinterrupt function. */
3182 if (mep_interrupt_p () || mep_disinterrupt_p ())
3183 return false;
3185 return true;
3189 mep_return_stackadj_rtx (void)
3191 return gen_rtx_REG (SImode, 10);
3195 mep_return_handler_rtx (void)
3197 return gen_rtx_REG (SImode, LP_REGNO);
3200 void
3201 mep_function_profiler (FILE *file)
3203 /* Always right at the beginning of the function. */
3204 fprintf (file, "\t# mep function profiler\n");
3205 fprintf (file, "\tadd\t$sp, -8\n");
3206 fprintf (file, "\tsw\t$0, ($sp)\n");
3207 fprintf (file, "\tldc\t$0, $lp\n");
3208 fprintf (file, "\tsw\t$0, 4($sp)\n");
3209 fprintf (file, "\tbsr\t__mep_mcount\n");
3210 fprintf (file, "\tlw\t$0, 4($sp)\n");
3211 fprintf (file, "\tstc\t$0, $lp\n");
3212 fprintf (file, "\tlw\t$0, ($sp)\n");
3213 fprintf (file, "\tadd\t$sp, 8\n\n");
3216 const char *
3217 mep_emit_bb_trace_ret (void)
3219 fprintf (asm_out_file, "\t# end of block profiling\n");
3220 fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3221 fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3222 fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3223 fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3224 fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3225 fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3226 fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3227 fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3228 fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3229 return "";
3232 #undef SAVE
3233 #undef RESTORE
3235 /* Operand Printing. */
3237 void
3238 mep_print_operand_address (FILE *stream, rtx address)
3240 if (GET_CODE (address) == MEM)
3241 address = XEXP (address, 0);
3242 else
3243 /* cf: gcc.dg/asm-4.c. */
3244 gcc_assert (GET_CODE (address) == REG);
3246 mep_print_operand (stream, address, 0);
3249 static struct
3251 char code;
3252 const char *pattern;
3253 const char *format;
3255 const conversions[] =
3257 { 0, "r", "0" },
3258 { 0, "m+ri", "3(2)" },
3259 { 0, "mr", "(1)" },
3260 { 0, "ms", "(1)" },
3261 { 0, "ml", "(1)" },
3262 { 0, "mLrs", "%lo(3)(2)" },
3263 { 0, "mLr+si", "%lo(4+5)(2)" },
3264 { 0, "m+ru2s", "%tpoff(5)(2)" },
3265 { 0, "m+ru3s", "%sdaoff(5)(2)" },
3266 { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3267 { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3268 { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3269 { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3270 { 0, "mi", "(1)" },
3271 { 0, "m+si", "(2+3)" },
3272 { 0, "m+li", "(2+3)" },
3273 { 0, "i", "0" },
3274 { 0, "s", "0" },
3275 { 0, "+si", "1+2" },
3276 { 0, "+u2si", "%tpoff(3+4)" },
3277 { 0, "+u3si", "%sdaoff(3+4)" },
3278 { 0, "l", "0" },
3279 { 'b', "i", "0" },
3280 { 'B', "i", "0" },
3281 { 'U', "i", "0" },
3282 { 'h', "i", "0" },
3283 { 'h', "Hs", "%hi(1)" },
3284 { 'I', "i", "0" },
3285 { 'I', "u2s", "%tpoff(2)" },
3286 { 'I', "u3s", "%sdaoff(2)" },
3287 { 'I', "+u2si", "%tpoff(3+4)" },
3288 { 'I', "+u3si", "%sdaoff(3+4)" },
3289 { 'J', "i", "0" },
3290 { 'P', "mr", "(1\\+),\\0" },
3291 { 'x', "i", "0" },
3292 { 0, 0, 0 }
3295 static int
3296 unique_bit_in (HOST_WIDE_INT i)
3298 switch (i & 0xff)
3300 case 0x01: case 0xfe: return 0;
3301 case 0x02: case 0xfd: return 1;
3302 case 0x04: case 0xfb: return 2;
3303 case 0x08: case 0xf7: return 3;
3304 case 0x10: case 0x7f: return 4;
3305 case 0x20: case 0xbf: return 5;
3306 case 0x40: case 0xdf: return 6;
3307 case 0x80: case 0xef: return 7;
3308 default:
3309 gcc_unreachable ();
3313 static int
3314 bit_size_for_clip (HOST_WIDE_INT i)
3316 int rv;
3318 for (rv = 0; rv < 31; rv ++)
3319 if (((HOST_WIDE_INT) 1 << rv) > i)
3320 return rv + 1;
3321 gcc_unreachable ();
3324 /* Print an operand to a assembler instruction. */
3326 void
3327 mep_print_operand (FILE *file, rtx x, int code)
3329 int i, j;
3330 const char *real_name;
3332 if (code == '<')
3334 /* Print a mnemonic to do CR <- CR moves. Find out which intrinsic
3335 we're using, then skip over the "mep_" part of its name. */
3336 const struct cgen_insn *insn;
3338 if (mep_get_move_insn (mep_cmov, &insn))
3339 fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3340 else
3341 mep_intrinsic_unavailable (mep_cmov);
3342 return;
3344 if (code == 'L')
3346 switch (GET_CODE (x))
3348 case AND:
3349 fputs ("clr", file);
3350 return;
3351 case IOR:
3352 fputs ("set", file);
3353 return;
3354 case XOR:
3355 fputs ("not", file);
3356 return;
3357 default:
3358 output_operand_lossage ("invalid %%L code");
3361 if (code == 'M')
3363 /* Print the second operand of a CR <- CR move. If we're using
3364 a two-operand instruction (i.e., a real cmov), then just print
3365 the operand normally. If we're using a "reg, reg, immediate"
3366 instruction such as caddi3, print the operand followed by a
3367 zero field. If we're using a three-register instruction,
3368 print the operand twice. */
3369 const struct cgen_insn *insn;
3371 mep_print_operand (file, x, 0);
3372 if (mep_get_move_insn (mep_cmov, &insn)
3373 && insn_data[insn->icode].n_operands == 3)
3375 fputs (", ", file);
3376 if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3377 mep_print_operand (file, x, 0);
3378 else
3379 mep_print_operand (file, const0_rtx, 0);
3381 return;
3384 encode_pattern (x);
3385 for (i = 0; conversions[i].pattern; i++)
3386 if (conversions[i].code == code
3387 && strcmp(conversions[i].pattern, pattern) == 0)
3389 for (j = 0; conversions[i].format[j]; j++)
3390 if (conversions[i].format[j] == '\\')
3392 fputc (conversions[i].format[j+1], file);
3393 j++;
3395 else if (ISDIGIT(conversions[i].format[j]))
3397 rtx r = patternr[conversions[i].format[j] - '0'];
3398 switch (GET_CODE (r))
3400 case REG:
3401 fprintf (file, "%s", reg_names [REGNO (r)]);
3402 break;
3403 case CONST_INT:
3404 switch (code)
3406 case 'b':
3407 fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3408 break;
3409 case 'B':
3410 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3411 break;
3412 case 'h':
3413 fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3414 break;
3415 case 'U':
3416 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3417 break;
3418 case 'J':
3419 fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3420 break;
3421 case 'x':
3422 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3423 && !(INTVAL (r) & 0xff))
3424 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3425 else
3426 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3427 break;
3428 case 'I':
3429 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3430 && conversions[i].format[j+1] == 0)
3432 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3433 fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3435 else
3436 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3437 break;
3438 default:
3439 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3440 break;
3442 break;
3443 case CONST_DOUBLE:
3444 fprintf(file, "[const_double 0x%lx]",
3445 (unsigned long) CONST_DOUBLE_HIGH(r));
3446 break;
3447 case SYMBOL_REF:
3448 real_name = targetm.strip_name_encoding (XSTR (r, 0));
3449 assemble_name (file, real_name);
3450 break;
3451 case LABEL_REF:
3452 output_asm_label (r);
3453 break;
3454 default:
3455 fprintf (stderr, "don't know how to print this operand:");
3456 debug_rtx (r);
3457 gcc_unreachable ();
3460 else
3462 if (conversions[i].format[j] == '+'
3463 && (!code || code == 'I')
3464 && ISDIGIT (conversions[i].format[j+1])
3465 && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3466 && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3467 continue;
3468 fputc(conversions[i].format[j], file);
3470 break;
3472 if (!conversions[i].pattern)
3474 error ("unconvertible operand %c %qs", code?code:'-', pattern);
3475 debug_rtx(x);
3478 return;
3481 void
3482 mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3483 int noperands ATTRIBUTE_UNUSED)
3485 /* Despite the fact that MeP is perfectly capable of branching and
3486 doing something else in the same bundle, gcc does jump
3487 optimization *after* scheduling, so we cannot trust the bundling
3488 flags on jump instructions. */
3489 if (GET_MODE (insn) == BImode
3490 && get_attr_slots (insn) != SLOTS_CORE)
3491 fputc ('+', asm_out_file);
3494 /* Function args in registers. */
3496 static void
3497 mep_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
3498 enum machine_mode mode ATTRIBUTE_UNUSED,
3499 tree type ATTRIBUTE_UNUSED, int *pretend_size,
3500 int second_time ATTRIBUTE_UNUSED)
3502 int nsave = 4 - (cum->nregs + 1);
3504 if (nsave > 0)
3505 cfun->machine->arg_regs_to_save = nsave;
3506 *pretend_size = nsave * 4;
3509 static int
3510 bytesize (const_tree type, enum machine_mode mode)
3512 if (mode == BLKmode)
3513 return int_size_in_bytes (type);
3514 return GET_MODE_SIZE (mode);
3517 static rtx
3518 mep_expand_builtin_saveregs (void)
3520 int bufsize, i, ns;
3521 rtx regbuf;
3523 ns = cfun->machine->arg_regs_to_save;
3524 if (TARGET_IVC2)
3526 bufsize = 8 * ((ns + 1) / 2) + 8 * ns;
3527 regbuf = assign_stack_local (SImode, bufsize, 64);
3529 else
3531 bufsize = ns * 4;
3532 regbuf = assign_stack_local (SImode, bufsize, 32);
3535 move_block_from_reg (5-ns, regbuf, ns);
3537 if (TARGET_IVC2)
3539 rtx tmp = gen_rtx_MEM (DImode, XEXP (regbuf, 0));
3540 int ofs = 8 * ((ns+1)/2);
3542 for (i=0; i<ns; i++)
3544 int rn = (4-ns) + i + 49;
3545 rtx ptr;
3547 ptr = offset_address (tmp, GEN_INT (ofs), 2);
3548 emit_move_insn (ptr, gen_rtx_REG (DImode, rn));
3549 ofs += 8;
3552 return XEXP (regbuf, 0);
3555 #define VECTOR_TYPE_P(t) (TREE_CODE(t) == VECTOR_TYPE)
3557 static tree
3558 mep_build_builtin_va_list (void)
3560 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3561 tree record;
3564 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3566 f_next_gp = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3567 get_identifier ("__va_next_gp"), ptr_type_node);
3568 f_next_gp_limit = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3569 get_identifier ("__va_next_gp_limit"),
3570 ptr_type_node);
3571 f_next_cop = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_cop"),
3572 ptr_type_node);
3573 f_next_stack = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_stack"),
3574 ptr_type_node);
3576 DECL_FIELD_CONTEXT (f_next_gp) = record;
3577 DECL_FIELD_CONTEXT (f_next_gp_limit) = record;
3578 DECL_FIELD_CONTEXT (f_next_cop) = record;
3579 DECL_FIELD_CONTEXT (f_next_stack) = record;
3581 TYPE_FIELDS (record) = f_next_gp;
3582 DECL_CHAIN (f_next_gp) = f_next_gp_limit;
3583 DECL_CHAIN (f_next_gp_limit) = f_next_cop;
3584 DECL_CHAIN (f_next_cop) = f_next_stack;
3586 layout_type (record);
3588 return record;
3591 static void
3592 mep_expand_va_start (tree valist, rtx nextarg)
3594 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3595 tree next_gp, next_gp_limit, next_cop, next_stack;
3596 tree t, u;
3597 int ns;
3599 ns = cfun->machine->arg_regs_to_save;
3601 f_next_gp = TYPE_FIELDS (va_list_type_node);
3602 f_next_gp_limit = DECL_CHAIN (f_next_gp);
3603 f_next_cop = DECL_CHAIN (f_next_gp_limit);
3604 f_next_stack = DECL_CHAIN (f_next_cop);
3606 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3607 NULL_TREE);
3608 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3609 valist, f_next_gp_limit, NULL_TREE);
3610 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3611 NULL_TREE);
3612 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3613 valist, f_next_stack, NULL_TREE);
3615 /* va_list.next_gp = expand_builtin_saveregs (); */
3616 u = make_tree (sizetype, expand_builtin_saveregs ());
3617 u = fold_convert (ptr_type_node, u);
3618 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp, u);
3619 TREE_SIDE_EFFECTS (t) = 1;
3620 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3622 /* va_list.next_gp_limit = va_list.next_gp + 4 * ns; */
3623 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
3624 size_int (4 * ns));
3625 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp_limit, u);
3626 TREE_SIDE_EFFECTS (t) = 1;
3627 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3629 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
3630 size_int (8 * ((ns+1)/2)));
3631 /* va_list.next_cop = ROUND_UP(va_list.next_gp_limit,8); */
3632 t = build2 (MODIFY_EXPR, ptr_type_node, next_cop, u);
3633 TREE_SIDE_EFFECTS (t) = 1;
3634 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3636 /* va_list.next_stack = nextarg; */
3637 u = make_tree (ptr_type_node, nextarg);
3638 t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
3639 TREE_SIDE_EFFECTS (t) = 1;
3640 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3643 static tree
3644 mep_gimplify_va_arg_expr (tree valist, tree type,
3645 gimple_seq *pre_p,
3646 gimple_seq *post_p ATTRIBUTE_UNUSED)
3648 HOST_WIDE_INT size, rsize;
3649 bool by_reference, ivc2_vec;
3650 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3651 tree next_gp, next_gp_limit, next_cop, next_stack;
3652 tree label_sover, label_selse;
3653 tree tmp, res_addr;
3655 ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type);
3657 size = int_size_in_bytes (type);
3658 by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0);
3660 if (by_reference)
3662 type = build_pointer_type (type);
3663 size = 4;
3665 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
3667 f_next_gp = TYPE_FIELDS (va_list_type_node);
3668 f_next_gp_limit = DECL_CHAIN (f_next_gp);
3669 f_next_cop = DECL_CHAIN (f_next_gp_limit);
3670 f_next_stack = DECL_CHAIN (f_next_cop);
3672 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3673 NULL_TREE);
3674 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3675 valist, f_next_gp_limit, NULL_TREE);
3676 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3677 NULL_TREE);
3678 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3679 valist, f_next_stack, NULL_TREE);
3681 /* if f_next_gp < f_next_gp_limit
3682 IF (VECTOR_P && IVC2)
3683 val = *f_next_cop;
3684 ELSE
3685 val = *f_next_gp;
3686 f_next_gp += 4;
3687 f_next_cop += 8;
3688 else
3689 label_selse:
3690 val = *f_next_stack;
3691 f_next_stack += rsize;
3692 label_sover:
3695 label_sover = create_artificial_label (UNKNOWN_LOCATION);
3696 label_selse = create_artificial_label (UNKNOWN_LOCATION);
3697 res_addr = create_tmp_var (ptr_type_node, NULL);
3699 tmp = build2 (GE_EXPR, boolean_type_node, next_gp,
3700 unshare_expr (next_gp_limit));
3701 tmp = build3 (COND_EXPR, void_type_node, tmp,
3702 build1 (GOTO_EXPR, void_type_node,
3703 unshare_expr (label_selse)),
3704 NULL_TREE);
3705 gimplify_and_add (tmp, pre_p);
3707 if (ivc2_vec)
3709 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_cop);
3710 gimplify_and_add (tmp, pre_p);
3712 else
3714 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_gp);
3715 gimplify_and_add (tmp, pre_p);
3718 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3719 unshare_expr (next_gp), size_int (4));
3720 gimplify_assign (unshare_expr (next_gp), tmp, pre_p);
3722 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3723 unshare_expr (next_cop), size_int (8));
3724 gimplify_assign (unshare_expr (next_cop), tmp, pre_p);
3726 tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (label_sover));
3727 gimplify_and_add (tmp, pre_p);
3729 /* - - */
3731 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_selse));
3732 gimplify_and_add (tmp, pre_p);
3734 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, unshare_expr (next_stack));
3735 gimplify_and_add (tmp, pre_p);
3737 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3738 unshare_expr (next_stack), size_int (rsize));
3739 gimplify_assign (unshare_expr (next_stack), tmp, pre_p);
3741 /* - - */
3743 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_sover));
3744 gimplify_and_add (tmp, pre_p);
3746 res_addr = fold_convert (build_pointer_type (type), res_addr);
3748 if (by_reference)
3749 res_addr = build_va_arg_indirect_ref (res_addr);
3751 return build_va_arg_indirect_ref (res_addr);
3754 void
3755 mep_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
3756 rtx libname ATTRIBUTE_UNUSED,
3757 tree fndecl ATTRIBUTE_UNUSED)
3759 pcum->nregs = 0;
3761 if (fntype && lookup_attribute ("vliw", TYPE_ATTRIBUTES (fntype)))
3762 pcum->vliw = 1;
3763 else
3764 pcum->vliw = 0;
3767 /* The ABI is thus: Arguments are in $1, $2, $3, $4, stack. Arguments
3768 larger than 4 bytes are passed indirectly. Return value in 0,
3769 unless bigger than 4 bytes, then the caller passes a pointer as the
3770 first arg. For varargs, we copy $1..$4 to the stack. */
3772 static rtx
3773 mep_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
3774 const_tree type ATTRIBUTE_UNUSED,
3775 bool named ATTRIBUTE_UNUSED)
3777 /* VOIDmode is a signal for the backend to pass data to the call
3778 expander via the second operand to the call pattern. We use
3779 this to determine whether to use "jsr" or "jsrv". */
3780 if (mode == VOIDmode)
3781 return GEN_INT (cum->vliw);
3783 /* If we havn't run out of argument registers, return the next. */
3784 if (cum->nregs < 4)
3786 if (type && TARGET_IVC2 && VECTOR_TYPE_P (type))
3787 return gen_rtx_REG (mode, cum->nregs + 49);
3788 else
3789 return gen_rtx_REG (mode, cum->nregs + 1);
3792 /* Otherwise the argument goes on the stack. */
3793 return NULL_RTX;
3796 static bool
3797 mep_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
3798 enum machine_mode mode,
3799 const_tree type,
3800 bool named ATTRIBUTE_UNUSED)
3802 int size = bytesize (type, mode);
3804 /* This is non-obvious, but yes, large values passed after we've run
3805 out of registers are *still* passed by reference - we put the
3806 address of the parameter on the stack, as well as putting the
3807 parameter itself elsewhere on the stack. */
3809 if (size <= 0 || size > 8)
3810 return true;
3811 if (size <= 4)
3812 return false;
3813 if (TARGET_IVC2 && cum->nregs < 4 && type != NULL_TREE && VECTOR_TYPE_P (type))
3814 return false;
3815 return true;
3818 static void
3819 mep_function_arg_advance (CUMULATIVE_ARGS *pcum,
3820 enum machine_mode mode ATTRIBUTE_UNUSED,
3821 const_tree type ATTRIBUTE_UNUSED,
3822 bool named ATTRIBUTE_UNUSED)
3824 pcum->nregs += 1;
3827 bool
3828 mep_return_in_memory (const_tree type, const_tree decl ATTRIBUTE_UNUSED)
3830 int size = bytesize (type, BLKmode);
3831 if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3832 return size > 0 && size <= 8 ? 0 : 1;
3833 return size > 0 && size <= 4 ? 0 : 1;
3836 static bool
3837 mep_narrow_volatile_bitfield (void)
3839 return true;
3840 return false;
3843 /* Implement FUNCTION_VALUE. All values are returned in $0. */
3846 mep_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
3848 if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3849 return gen_rtx_REG (TYPE_MODE (type), 48);
3850 return gen_rtx_REG (TYPE_MODE (type), RETURN_VALUE_REGNUM);
3853 /* Implement LIBCALL_VALUE, using the same rules as mep_function_value. */
3856 mep_libcall_value (enum machine_mode mode)
3858 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
3861 /* Handle pipeline hazards. */
3863 typedef enum { op_none, op_stc, op_fsft, op_ret } op_num;
3864 static const char *opnames[] = { "", "stc", "fsft", "ret" };
3866 static int prev_opcode = 0;
3868 /* This isn't as optimal as it could be, because we don't know what
3869 control register the STC opcode is storing in. We only need to add
3870 the nop if it's the relevent register, but we add it for irrelevent
3871 registers also. */
3873 void
3874 mep_asm_output_opcode (FILE *file, const char *ptr)
3876 int this_opcode = op_none;
3877 const char *hazard = 0;
3879 switch (*ptr)
3881 case 'f':
3882 if (strncmp (ptr, "fsft", 4) == 0 && !ISGRAPH (ptr[4]))
3883 this_opcode = op_fsft;
3884 break;
3885 case 'r':
3886 if (strncmp (ptr, "ret", 3) == 0 && !ISGRAPH (ptr[3]))
3887 this_opcode = op_ret;
3888 break;
3889 case 's':
3890 if (strncmp (ptr, "stc", 3) == 0 && !ISGRAPH (ptr[3]))
3891 this_opcode = op_stc;
3892 break;
3895 if (prev_opcode == op_stc && this_opcode == op_fsft)
3896 hazard = "nop";
3897 if (prev_opcode == op_stc && this_opcode == op_ret)
3898 hazard = "nop";
3900 if (hazard)
3901 fprintf(file, "%s\t# %s-%s hazard\n\t",
3902 hazard, opnames[prev_opcode], opnames[this_opcode]);
3904 prev_opcode = this_opcode;
3907 /* Handle attributes. */
3909 static tree
3910 mep_validate_based_tiny (tree *node, tree name, tree args,
3911 int flags ATTRIBUTE_UNUSED, bool *no_add)
3913 if (TREE_CODE (*node) != VAR_DECL
3914 && TREE_CODE (*node) != POINTER_TYPE
3915 && TREE_CODE (*node) != TYPE_DECL)
3917 warning (0, "%qE attribute only applies to variables", name);
3918 *no_add = true;
3920 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3922 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3924 warning (0, "address region attributes not allowed with auto storage class");
3925 *no_add = true;
3927 /* Ignore storage attribute of pointed to variable: char __far * x; */
3928 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3930 warning (0, "address region attributes on pointed-to types ignored");
3931 *no_add = true;
3935 return NULL_TREE;
3938 static int
3939 mep_multiple_address_regions (tree list, bool check_section_attr)
3941 tree a;
3942 int count_sections = 0;
3943 int section_attr_count = 0;
3945 for (a = list; a; a = TREE_CHAIN (a))
3947 if (is_attribute_p ("based", TREE_PURPOSE (a))
3948 || is_attribute_p ("tiny", TREE_PURPOSE (a))
3949 || is_attribute_p ("near", TREE_PURPOSE (a))
3950 || is_attribute_p ("far", TREE_PURPOSE (a))
3951 || is_attribute_p ("io", TREE_PURPOSE (a)))
3952 count_sections ++;
3953 if (check_section_attr)
3954 section_attr_count += is_attribute_p ("section", TREE_PURPOSE (a));
3957 if (check_section_attr)
3958 return section_attr_count;
3959 else
3960 return count_sections;
3963 #define MEP_ATTRIBUTES(decl) \
3964 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
3965 : DECL_ATTRIBUTES (decl) \
3966 ? (DECL_ATTRIBUTES (decl)) \
3967 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
3969 static tree
3970 mep_validate_near_far (tree *node, tree name, tree args,
3971 int flags ATTRIBUTE_UNUSED, bool *no_add)
3973 if (TREE_CODE (*node) != VAR_DECL
3974 && TREE_CODE (*node) != FUNCTION_DECL
3975 && TREE_CODE (*node) != METHOD_TYPE
3976 && TREE_CODE (*node) != POINTER_TYPE
3977 && TREE_CODE (*node) != TYPE_DECL)
3979 warning (0, "%qE attribute only applies to variables and functions",
3980 name);
3981 *no_add = true;
3983 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3985 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3987 warning (0, "address region attributes not allowed with auto storage class");
3988 *no_add = true;
3990 /* Ignore storage attribute of pointed to variable: char __far * x; */
3991 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3993 warning (0, "address region attributes on pointed-to types ignored");
3994 *no_add = true;
3997 else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0)
3999 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
4000 name, DECL_NAME (*node), DECL_SOURCE_LINE (*node));
4001 DECL_ATTRIBUTES (*node) = NULL_TREE;
4003 return NULL_TREE;
4006 static tree
4007 mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4008 int flags ATTRIBUTE_UNUSED, bool *no_add)
4010 if (TREE_CODE (*node) != FUNCTION_DECL
4011 && TREE_CODE (*node) != METHOD_TYPE)
4013 warning (0, "%qE attribute only applies to functions", name);
4014 *no_add = true;
4016 return NULL_TREE;
4019 static tree
4020 mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4021 int flags ATTRIBUTE_UNUSED, bool *no_add)
4023 tree function_type;
4025 if (TREE_CODE (*node) != FUNCTION_DECL)
4027 warning (0, "%qE attribute only applies to functions", name);
4028 *no_add = true;
4029 return NULL_TREE;
4032 if (DECL_DECLARED_INLINE_P (*node))
4033 error ("cannot inline interrupt function %qE", DECL_NAME (*node));
4034 DECL_UNINLINABLE (*node) = 1;
4036 function_type = TREE_TYPE (*node);
4038 if (TREE_TYPE (function_type) != void_type_node)
4039 error ("interrupt function must have return type of void");
4041 if (prototype_p (function_type)
4042 && (TREE_VALUE (TYPE_ARG_TYPES (function_type)) != void_type_node
4043 || TREE_CHAIN (TYPE_ARG_TYPES (function_type)) != NULL_TREE))
4044 error ("interrupt function must have no arguments");
4046 return NULL_TREE;
4049 static tree
4050 mep_validate_io_cb (tree *node, tree name, tree args,
4051 int flags ATTRIBUTE_UNUSED, bool *no_add)
4053 if (TREE_CODE (*node) != VAR_DECL)
4055 warning (0, "%qE attribute only applies to variables", name);
4056 *no_add = true;
4059 if (args != NULL_TREE)
4061 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
4062 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
4063 if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
4065 warning (0, "%qE attribute allows only an integer constant argument",
4066 name);
4067 *no_add = true;
4071 if (*no_add == false && !TARGET_IO_NO_VOLATILE)
4072 TREE_THIS_VOLATILE (*node) = 1;
4074 return NULL_TREE;
4077 static tree
4078 mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4079 int flags ATTRIBUTE_UNUSED, bool *no_add)
4081 if (TREE_CODE (*node) != FUNCTION_TYPE
4082 && TREE_CODE (*node) != FUNCTION_DECL
4083 && TREE_CODE (*node) != METHOD_TYPE
4084 && TREE_CODE (*node) != FIELD_DECL
4085 && TREE_CODE (*node) != TYPE_DECL)
4087 static int gave_pointer_note = 0;
4088 static int gave_array_note = 0;
4089 static const char * given_type = NULL;
4091 given_type = tree_code_name[TREE_CODE (*node)];
4092 if (TREE_CODE (*node) == POINTER_TYPE)
4093 given_type = "pointers";
4094 if (TREE_CODE (*node) == ARRAY_TYPE)
4095 given_type = "arrays";
4097 if (given_type)
4098 warning (0, "%qE attribute only applies to functions, not %s",
4099 name, given_type);
4100 else
4101 warning (0, "%qE attribute only applies to functions",
4102 name);
4103 *no_add = true;
4105 if (TREE_CODE (*node) == POINTER_TYPE
4106 && !gave_pointer_note)
4108 inform (input_location,
4109 "to describe a pointer to a VLIW function, use syntax like this:\n%s",
4110 " typedef int (__vliw *vfuncptr) ();");
4111 gave_pointer_note = 1;
4114 if (TREE_CODE (*node) == ARRAY_TYPE
4115 && !gave_array_note)
4117 inform (input_location,
4118 "to describe an array of VLIW function pointers, use syntax like this:\n%s",
4119 " typedef int (__vliw *vfuncptr[]) ();");
4120 gave_array_note = 1;
4123 if (!TARGET_VLIW)
4124 error ("VLIW functions are not allowed without a VLIW configuration");
4125 return NULL_TREE;
4128 static const struct attribute_spec mep_attribute_table[11] =
4130 /* name min max decl type func handler
4131 affects_type_identity */
4132 { "based", 0, 0, false, false, false, mep_validate_based_tiny, false },
4133 { "tiny", 0, 0, false, false, false, mep_validate_based_tiny, false },
4134 { "near", 0, 0, false, false, false, mep_validate_near_far, false },
4135 { "far", 0, 0, false, false, false, mep_validate_near_far, false },
4136 { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt,
4137 false },
4138 { "interrupt", 0, 0, false, false, false, mep_validate_interrupt, false },
4139 { "io", 0, 1, false, false, false, mep_validate_io_cb, false },
4140 { "cb", 0, 1, false, false, false, mep_validate_io_cb, false },
4141 { "vliw", 0, 0, false, true, false, mep_validate_vliw, false },
4142 { NULL, 0, 0, false, false, false, NULL, false }
4145 static bool
4146 mep_function_attribute_inlinable_p (const_tree callee)
4148 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee));
4149 if (!attrs) attrs = DECL_ATTRIBUTES (callee);
4150 return (lookup_attribute ("disinterrupt", attrs) == 0
4151 && lookup_attribute ("interrupt", attrs) == 0);
4154 static bool
4155 mep_can_inline_p (tree caller, tree callee)
4157 if (TREE_CODE (callee) == ADDR_EXPR)
4158 callee = TREE_OPERAND (callee, 0);
4160 if (!mep_vliw_function_p (caller)
4161 && mep_vliw_function_p (callee))
4163 return false;
4165 return true;
4168 #define FUNC_CALL 1
4169 #define FUNC_DISINTERRUPT 2
4172 struct GTY(()) pragma_entry {
4173 int used;
4174 int flag;
4175 const char *funcname;
4177 typedef struct pragma_entry pragma_entry;
4179 /* Hash table of farcall-tagged sections. */
4180 static GTY((param_is (pragma_entry))) htab_t pragma_htab;
4182 static int
4183 pragma_entry_eq (const void *p1, const void *p2)
4185 const pragma_entry *old = (const pragma_entry *) p1;
4186 const char *new_name = (const char *) p2;
4188 return strcmp (old->funcname, new_name) == 0;
4191 static hashval_t
4192 pragma_entry_hash (const void *p)
4194 const pragma_entry *old = (const pragma_entry *) p;
4195 return htab_hash_string (old->funcname);
4198 static void
4199 mep_note_pragma_flag (const char *funcname, int flag)
4201 pragma_entry **slot;
4203 if (!pragma_htab)
4204 pragma_htab = htab_create_ggc (31, pragma_entry_hash,
4205 pragma_entry_eq, NULL);
4207 slot = (pragma_entry **)
4208 htab_find_slot_with_hash (pragma_htab, funcname,
4209 htab_hash_string (funcname), INSERT);
4211 if (!*slot)
4213 *slot = ggc_alloc_pragma_entry ();
4214 (*slot)->flag = 0;
4215 (*slot)->used = 0;
4216 (*slot)->funcname = ggc_strdup (funcname);
4218 (*slot)->flag |= flag;
4221 static bool
4222 mep_lookup_pragma_flag (const char *funcname, int flag)
4224 pragma_entry **slot;
4226 if (!pragma_htab)
4227 return false;
4229 if (funcname[0] == '@' && funcname[2] == '.')
4230 funcname += 3;
4232 slot = (pragma_entry **)
4233 htab_find_slot_with_hash (pragma_htab, funcname,
4234 htab_hash_string (funcname), NO_INSERT);
4235 if (slot && *slot && ((*slot)->flag & flag))
4237 (*slot)->used |= flag;
4238 return true;
4240 return false;
4243 bool
4244 mep_lookup_pragma_call (const char *funcname)
4246 return mep_lookup_pragma_flag (funcname, FUNC_CALL);
4249 void
4250 mep_note_pragma_call (const char *funcname)
4252 mep_note_pragma_flag (funcname, FUNC_CALL);
4255 bool
4256 mep_lookup_pragma_disinterrupt (const char *funcname)
4258 return mep_lookup_pragma_flag (funcname, FUNC_DISINTERRUPT);
4261 void
4262 mep_note_pragma_disinterrupt (const char *funcname)
4264 mep_note_pragma_flag (funcname, FUNC_DISINTERRUPT);
4267 static int
4268 note_unused_pragma_disinterrupt (void **slot, void *data ATTRIBUTE_UNUSED)
4270 const pragma_entry *d = (const pragma_entry *)(*slot);
4272 if ((d->flag & FUNC_DISINTERRUPT)
4273 && !(d->used & FUNC_DISINTERRUPT))
4274 warning (0, "\"#pragma disinterrupt %s\" not used", d->funcname);
4275 return 1;
4278 void
4279 mep_file_cleanups (void)
4281 if (pragma_htab)
4282 htab_traverse (pragma_htab, note_unused_pragma_disinterrupt, NULL);
4285 /* These three functions provide a bridge between the pramgas that
4286 affect register classes, and the functions that maintain them. We
4287 can't call those functions directly as pragma handling is part of
4288 the front end and doesn't have direct access to them. */
4290 void
4291 mep_save_register_info (void)
4293 save_register_info ();
4296 void
4297 mep_reinit_regs (void)
4299 reinit_regs ();
4302 void
4303 mep_init_regs (void)
4305 init_regs ();
4310 static int
4311 mep_attrlist_to_encoding (tree list, tree decl)
4313 if (mep_multiple_address_regions (list, false) > 1)
4315 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
4316 TREE_PURPOSE (TREE_CHAIN (list)),
4317 DECL_NAME (decl),
4318 DECL_SOURCE_LINE (decl));
4319 TREE_CHAIN (list) = NULL_TREE;
4322 while (list)
4324 if (is_attribute_p ("based", TREE_PURPOSE (list)))
4325 return 'b';
4326 if (is_attribute_p ("tiny", TREE_PURPOSE (list)))
4327 return 't';
4328 if (is_attribute_p ("near", TREE_PURPOSE (list)))
4329 return 'n';
4330 if (is_attribute_p ("far", TREE_PURPOSE (list)))
4331 return 'f';
4332 if (is_attribute_p ("io", TREE_PURPOSE (list)))
4334 if (TREE_VALUE (list)
4335 && TREE_VALUE (TREE_VALUE (list))
4336 && TREE_CODE (TREE_VALUE (TREE_VALUE (list))) == INTEGER_CST)
4338 int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(list)));
4339 if (location >= 0
4340 && location <= 0x1000000)
4341 return 'i';
4343 return 'I';
4345 if (is_attribute_p ("cb", TREE_PURPOSE (list)))
4346 return 'c';
4347 list = TREE_CHAIN (list);
4349 if (TARGET_TF
4350 && TREE_CODE (decl) == FUNCTION_DECL
4351 && DECL_SECTION_NAME (decl) == 0)
4352 return 'f';
4353 return 0;
4356 static int
4357 mep_comp_type_attributes (const_tree t1, const_tree t2)
4359 int vliw1, vliw2;
4361 vliw1 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t1)) != 0);
4362 vliw2 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t2)) != 0);
4364 if (vliw1 != vliw2)
4365 return 0;
4367 return 1;
4370 static void
4371 mep_insert_attributes (tree decl, tree *attributes)
4373 int size;
4374 const char *secname = 0;
4375 tree attrib, attrlist;
4376 char encoding;
4378 if (TREE_CODE (decl) == FUNCTION_DECL)
4380 const char *funcname = IDENTIFIER_POINTER (DECL_NAME (decl));
4382 if (mep_lookup_pragma_disinterrupt (funcname))
4384 attrib = build_tree_list (get_identifier ("disinterrupt"), NULL_TREE);
4385 *attributes = chainon (*attributes, attrib);
4389 if (TREE_CODE (decl) != VAR_DECL
4390 || ! (TREE_PUBLIC (decl) || TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
4391 return;
4393 if (TREE_READONLY (decl) && TARGET_DC)
4394 /* -mdc means that const variables default to the near section,
4395 regardless of the size cutoff. */
4396 return;
4398 /* User specified an attribute, so override the default.
4399 Ignore storage attribute of pointed to variable. char __far * x; */
4400 if (! (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE))
4402 if (TYPE_P (decl) && TYPE_ATTRIBUTES (decl) && *attributes)
4403 TYPE_ATTRIBUTES (decl) = NULL_TREE;
4404 else if (DECL_ATTRIBUTES (decl) && *attributes)
4405 DECL_ATTRIBUTES (decl) = NULL_TREE;
4408 attrlist = *attributes ? *attributes : DECL_ATTRIBUTES (decl);
4409 encoding = mep_attrlist_to_encoding (attrlist, decl);
4410 if (!encoding && TYPE_P (TREE_TYPE (decl)))
4412 attrlist = TYPE_ATTRIBUTES (TREE_TYPE (decl));
4413 encoding = mep_attrlist_to_encoding (attrlist, decl);
4415 if (encoding)
4417 /* This means that the declaration has a specific section
4418 attribute, so we should not apply the default rules. */
4420 if (encoding == 'i' || encoding == 'I')
4422 tree attr = lookup_attribute ("io", attrlist);
4423 if (attr
4424 && TREE_VALUE (attr)
4425 && TREE_VALUE (TREE_VALUE(attr)))
4427 int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr)));
4428 static tree previous_value = 0;
4429 static int previous_location = 0;
4430 static tree previous_name = 0;
4432 /* We take advantage of the fact that gcc will reuse the
4433 same tree pointer when applying an attribute to a
4434 list of decls, but produce a new tree for attributes
4435 on separate source lines, even when they're textually
4436 identical. This is the behavior we want. */
4437 if (TREE_VALUE (attr) == previous_value
4438 && location == previous_location)
4440 warning(0, "__io address 0x%x is the same for %qE and %qE",
4441 location, previous_name, DECL_NAME (decl));
4443 previous_name = DECL_NAME (decl);
4444 previous_location = location;
4445 previous_value = TREE_VALUE (attr);
4448 return;
4452 /* Declarations of arrays can change size. Don't trust them. */
4453 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
4454 size = 0;
4455 else
4456 size = int_size_in_bytes (TREE_TYPE (decl));
4458 if (TARGET_RAND_TPGP && size <= 4 && size > 0)
4460 if (TREE_PUBLIC (decl)
4461 || DECL_EXTERNAL (decl)
4462 || TREE_STATIC (decl))
4464 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
4465 int key = 0;
4467 while (*name)
4468 key += *name++;
4470 switch (key & 3)
4472 case 0:
4473 secname = "based";
4474 break;
4475 case 1:
4476 secname = "tiny";
4477 break;
4478 case 2:
4479 secname = "far";
4480 break;
4481 default:
4486 else
4488 if (size <= mep_based_cutoff && size > 0)
4489 secname = "based";
4490 else if (size <= mep_tiny_cutoff && size > 0)
4491 secname = "tiny";
4492 else if (TARGET_L)
4493 secname = "far";
4496 if (mep_const_section && TREE_READONLY (decl))
4498 if (strcmp (mep_const_section, "tiny") == 0)
4499 secname = "tiny";
4500 else if (strcmp (mep_const_section, "near") == 0)
4501 return;
4502 else if (strcmp (mep_const_section, "far") == 0)
4503 secname = "far";
4506 if (!secname)
4507 return;
4509 if (!mep_multiple_address_regions (*attributes, true)
4510 && !mep_multiple_address_regions (DECL_ATTRIBUTES (decl), false))
4512 attrib = build_tree_list (get_identifier (secname), NULL_TREE);
4514 /* Chain the attribute directly onto the variable's DECL_ATTRIBUTES
4515 in order to avoid the POINTER_TYPE bypasses in mep_validate_near_far
4516 and mep_validate_based_tiny. */
4517 DECL_ATTRIBUTES (decl) = chainon (DECL_ATTRIBUTES (decl), attrib);
4521 static void
4522 mep_encode_section_info (tree decl, rtx rtl, int first)
4524 rtx rtlname;
4525 const char *oldname;
4526 const char *secname;
4527 char encoding;
4528 char *newname;
4529 tree idp;
4530 int maxsize;
4531 tree type;
4532 tree mep_attributes;
4534 if (! first)
4535 return;
4537 if (TREE_CODE (decl) != VAR_DECL
4538 && TREE_CODE (decl) != FUNCTION_DECL)
4539 return;
4541 rtlname = XEXP (rtl, 0);
4542 if (GET_CODE (rtlname) == SYMBOL_REF)
4543 oldname = XSTR (rtlname, 0);
4544 else if (GET_CODE (rtlname) == MEM
4545 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4546 oldname = XSTR (XEXP (rtlname, 0), 0);
4547 else
4548 gcc_unreachable ();
4550 type = TREE_TYPE (decl);
4551 if (type == error_mark_node)
4552 return;
4553 mep_attributes = MEP_ATTRIBUTES (decl);
4555 encoding = mep_attrlist_to_encoding (mep_attributes, decl);
4557 if (encoding)
4559 newname = (char *) alloca (strlen (oldname) + 4);
4560 sprintf (newname, "@%c.%s", encoding, oldname);
4561 idp = get_identifier (newname);
4562 XEXP (rtl, 0) =
4563 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4564 SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4565 SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4567 switch (encoding)
4569 case 'b':
4570 maxsize = 128;
4571 secname = "based";
4572 break;
4573 case 't':
4574 maxsize = 65536;
4575 secname = "tiny";
4576 break;
4577 case 'n':
4578 maxsize = 0x1000000;
4579 secname = "near";
4580 break;
4581 default:
4582 maxsize = 0;
4583 secname = 0;
4584 break;
4586 if (maxsize && int_size_in_bytes (TREE_TYPE (decl)) > maxsize)
4588 warning (0, "variable %s (%ld bytes) is too large for the %s section (%d bytes)",
4589 oldname,
4590 (long) int_size_in_bytes (TREE_TYPE (decl)),
4591 secname,
4592 maxsize);
4597 const char *
4598 mep_strip_name_encoding (const char *sym)
4600 while (1)
4602 if (*sym == '*')
4603 sym++;
4604 else if (*sym == '@' && sym[2] == '.')
4605 sym += 3;
4606 else
4607 return sym;
4611 static section *
4612 mep_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
4613 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4615 int readonly = 1;
4616 int encoding;
4618 switch (TREE_CODE (decl))
4620 case VAR_DECL:
4621 if (!TREE_READONLY (decl)
4622 || TREE_SIDE_EFFECTS (decl)
4623 || !DECL_INITIAL (decl)
4624 || (DECL_INITIAL (decl) != error_mark_node
4625 && !TREE_CONSTANT (DECL_INITIAL (decl))))
4626 readonly = 0;
4627 break;
4628 case CONSTRUCTOR:
4629 if (! TREE_CONSTANT (decl))
4630 readonly = 0;
4631 break;
4633 default:
4634 break;
4637 if (TREE_CODE (decl) == FUNCTION_DECL)
4639 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4641 if (name[0] == '@' && name[2] == '.')
4642 encoding = name[1];
4643 else
4644 encoding = 0;
4646 if (flag_function_sections || DECL_ONE_ONLY (decl))
4647 mep_unique_section (decl, 0);
4648 else if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4650 if (encoding == 'f')
4651 return vftext_section;
4652 else
4653 return vtext_section;
4655 else if (encoding == 'f')
4656 return ftext_section;
4657 else
4658 return text_section;
4661 if (TREE_CODE (decl) == VAR_DECL)
4663 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4665 if (name[0] == '@' && name[2] == '.')
4666 switch (name[1])
4668 case 'b':
4669 return based_section;
4671 case 't':
4672 if (readonly)
4673 return srodata_section;
4674 if (DECL_INITIAL (decl))
4675 return sdata_section;
4676 return tinybss_section;
4678 case 'f':
4679 if (readonly)
4680 return frodata_section;
4681 return far_section;
4683 case 'i':
4684 case 'I':
4685 error_at (DECL_SOURCE_LOCATION (decl),
4686 "variable %D of type %<io%> must be uninitialized", decl);
4687 return data_section;
4689 case 'c':
4690 error_at (DECL_SOURCE_LOCATION (decl),
4691 "variable %D of type %<cb%> must be uninitialized", decl);
4692 return data_section;
4696 if (readonly)
4697 return readonly_data_section;
4699 return data_section;
4702 static void
4703 mep_unique_section (tree decl, int reloc)
4705 static const char *prefixes[][2] =
4707 { ".text.", ".gnu.linkonce.t." },
4708 { ".rodata.", ".gnu.linkonce.r." },
4709 { ".data.", ".gnu.linkonce.d." },
4710 { ".based.", ".gnu.linkonce.based." },
4711 { ".sdata.", ".gnu.linkonce.s." },
4712 { ".far.", ".gnu.linkonce.far." },
4713 { ".ftext.", ".gnu.linkonce.ft." },
4714 { ".frodata.", ".gnu.linkonce.frd." },
4715 { ".srodata.", ".gnu.linkonce.srd." },
4716 { ".vtext.", ".gnu.linkonce.v." },
4717 { ".vftext.", ".gnu.linkonce.vf." }
4719 int sec = 2; /* .data */
4720 int len;
4721 const char *name, *prefix;
4722 char *string;
4724 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4725 if (DECL_RTL (decl))
4726 name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4728 if (TREE_CODE (decl) == FUNCTION_DECL)
4730 if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4731 sec = 9; /* .vtext */
4732 else
4733 sec = 0; /* .text */
4735 else if (decl_readonly_section (decl, reloc))
4736 sec = 1; /* .rodata */
4738 if (name[0] == '@' && name[2] == '.')
4740 switch (name[1])
4742 case 'b':
4743 sec = 3; /* .based */
4744 break;
4745 case 't':
4746 if (sec == 1)
4747 sec = 8; /* .srodata */
4748 else
4749 sec = 4; /* .sdata */
4750 break;
4751 case 'f':
4752 if (sec == 0)
4753 sec = 6; /* .ftext */
4754 else if (sec == 9)
4755 sec = 10; /* .vftext */
4756 else if (sec == 1)
4757 sec = 7; /* .frodata */
4758 else
4759 sec = 5; /* .far. */
4760 break;
4762 name += 3;
4765 prefix = prefixes[sec][DECL_ONE_ONLY(decl)];
4766 len = strlen (name) + strlen (prefix);
4767 string = (char *) alloca (len + 1);
4769 sprintf (string, "%s%s", prefix, name);
4771 DECL_SECTION_NAME (decl) = build_string (len, string);
4774 /* Given a decl, a section name, and whether the decl initializer
4775 has relocs, choose attributes for the section. */
4777 #define SECTION_MEP_VLIW SECTION_MACH_DEP
4779 static unsigned int
4780 mep_section_type_flags (tree decl, const char *name, int reloc)
4782 unsigned int flags = default_section_type_flags (decl, name, reloc);
4784 if (decl && TREE_CODE (decl) == FUNCTION_DECL
4785 && lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
4786 flags |= SECTION_MEP_VLIW;
4788 return flags;
4791 /* Switch to an arbitrary section NAME with attributes as specified
4792 by FLAGS. ALIGN specifies any known alignment requirements for
4793 the section; 0 if the default should be used.
4795 Differs from the standard ELF version only in support of VLIW mode. */
4797 static void
4798 mep_asm_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED)
4800 char flagchars[8], *f = flagchars;
4801 const char *type;
4803 if (!(flags & SECTION_DEBUG))
4804 *f++ = 'a';
4805 if (flags & SECTION_WRITE)
4806 *f++ = 'w';
4807 if (flags & SECTION_CODE)
4808 *f++ = 'x';
4809 if (flags & SECTION_SMALL)
4810 *f++ = 's';
4811 if (flags & SECTION_MEP_VLIW)
4812 *f++ = 'v';
4813 *f = '\0';
4815 if (flags & SECTION_BSS)
4816 type = "nobits";
4817 else
4818 type = "progbits";
4820 fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
4821 name, flagchars, type);
4823 if (flags & SECTION_CODE)
4824 fputs ((flags & SECTION_MEP_VLIW ? "\t.vliw\n" : "\t.core\n"),
4825 asm_out_file);
4828 void
4829 mep_output_aligned_common (FILE *stream, tree decl, const char *name,
4830 int size, int align, int global)
4832 /* We intentionally don't use mep_section_tag() here. */
4833 if (name[0] == '@'
4834 && (name[1] == 'i' || name[1] == 'I' || name[1] == 'c')
4835 && name[2] == '.')
4837 int location = -1;
4838 tree attr = lookup_attribute ((name[1] == 'c' ? "cb" : "io"),
4839 DECL_ATTRIBUTES (decl));
4840 if (attr
4841 && TREE_VALUE (attr)
4842 && TREE_VALUE (TREE_VALUE(attr)))
4843 location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr)));
4844 if (location == -1)
4845 return;
4846 if (global)
4848 fprintf (stream, "\t.globl\t");
4849 assemble_name (stream, name);
4850 fprintf (stream, "\n");
4852 assemble_name (stream, name);
4853 fprintf (stream, " = %d\n", location);
4854 return;
4856 if (name[0] == '@' && name[2] == '.')
4858 const char *sec = 0;
4859 switch (name[1])
4861 case 'b':
4862 switch_to_section (based_section);
4863 sec = ".based";
4864 break;
4865 case 't':
4866 switch_to_section (tinybss_section);
4867 sec = ".sbss";
4868 break;
4869 case 'f':
4870 switch_to_section (farbss_section);
4871 sec = ".farbss";
4872 break;
4874 if (sec)
4876 const char *name2;
4877 int p2align = 0;
4879 while (align > BITS_PER_UNIT)
4881 align /= 2;
4882 p2align ++;
4884 name2 = targetm.strip_name_encoding (name);
4885 if (global)
4886 fprintf (stream, "\t.globl\t%s\n", name2);
4887 fprintf (stream, "\t.p2align %d\n", p2align);
4888 fprintf (stream, "\t.type\t%s,@object\n", name2);
4889 fprintf (stream, "\t.size\t%s,%d\n", name2, size);
4890 fprintf (stream, "%s:\n\t.zero\t%d\n", name2, size);
4891 return;
4895 if (!global)
4897 fprintf (stream, "\t.local\t");
4898 assemble_name (stream, name);
4899 fprintf (stream, "\n");
4901 fprintf (stream, "\t.comm\t");
4902 assemble_name (stream, name);
4903 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4906 /* Trampolines. */
4908 static void
4909 mep_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
4911 rtx addr = XEXP (m_tramp, 0);
4912 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
4914 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__mep_trampoline_helper"),
4915 LCT_NORMAL, VOIDmode, 3,
4916 addr, Pmode,
4917 fnaddr, Pmode,
4918 static_chain, Pmode);
4921 /* Experimental Reorg. */
4923 static bool
4924 mep_mentioned_p (rtx in,
4925 rtx reg, /* NULL for mem */
4926 int modes_too) /* if nonzero, modes must match also. */
4928 const char *fmt;
4929 int i;
4930 enum rtx_code code;
4932 if (in == 0)
4933 return false;
4934 if (reg && GET_CODE (reg) != REG)
4935 return false;
4937 if (GET_CODE (in) == LABEL_REF)
4938 return (reg == 0);
4940 code = GET_CODE (in);
4942 switch (code)
4944 case MEM:
4945 if (reg)
4946 return mep_mentioned_p (XEXP (in, 0), reg, modes_too);
4947 return true;
4949 case REG:
4950 if (!reg)
4951 return false;
4952 if (modes_too && (GET_MODE (in) != GET_MODE (reg)))
4953 return false;
4954 return (REGNO (in) == REGNO (reg));
4956 case SCRATCH:
4957 case CC0:
4958 case PC:
4959 case CONST_INT:
4960 case CONST_DOUBLE:
4961 return false;
4963 default:
4964 break;
4967 /* Set's source should be read-only. */
4968 if (code == SET && !reg)
4969 return mep_mentioned_p (SET_DEST (in), reg, modes_too);
4971 fmt = GET_RTX_FORMAT (code);
4973 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4975 if (fmt[i] == 'E')
4977 register int j;
4978 for (j = XVECLEN (in, i) - 1; j >= 0; j--)
4979 if (mep_mentioned_p (XVECEXP (in, i, j), reg, modes_too))
4980 return true;
4982 else if (fmt[i] == 'e'
4983 && mep_mentioned_p (XEXP (in, i), reg, modes_too))
4984 return true;
4986 return false;
4989 #define EXPERIMENTAL_REGMOVE_REORG 1
4991 #if EXPERIMENTAL_REGMOVE_REORG
4993 static int
4994 mep_compatible_reg_class (int r1, int r2)
4996 if (GR_REGNO_P (r1) && GR_REGNO_P (r2))
4997 return 1;
4998 if (CR_REGNO_P (r1) && CR_REGNO_P (r2))
4999 return 1;
5000 return 0;
5003 static void
5004 mep_reorg_regmove (rtx insns)
5006 rtx insn, next, pat, follow, *where;
5007 int count = 0, done = 0, replace, before = 0;
5009 if (dump_file)
5010 for (insn = insns; insn; insn = NEXT_INSN (insn))
5011 if (GET_CODE (insn) == INSN)
5012 before++;
5014 /* We're looking for (set r2 r1) moves where r1 dies, followed by a
5015 set that uses the r2 and r2 dies there. We replace r2 with r1
5016 and see if it's still a valid insn. If so, delete the first set.
5017 Copied from reorg.c. */
5019 while (!done)
5021 done = 1;
5022 for (insn = insns; insn; insn = next)
5024 next = NEXT_INSN (insn);
5025 if (GET_CODE (insn) != INSN)
5026 continue;
5027 pat = PATTERN (insn);
5029 replace = 0;
5031 if (GET_CODE (pat) == SET
5032 && GET_CODE (SET_SRC (pat)) == REG
5033 && GET_CODE (SET_DEST (pat)) == REG
5034 && find_regno_note (insn, REG_DEAD, REGNO (SET_SRC (pat)))
5035 && mep_compatible_reg_class (REGNO (SET_SRC (pat)), REGNO (SET_DEST (pat))))
5037 follow = next_nonnote_insn (insn);
5038 if (dump_file)
5039 fprintf (dump_file, "superfluous moves: considering %d\n", INSN_UID (insn));
5041 while (follow && GET_CODE (follow) == INSN
5042 && GET_CODE (PATTERN (follow)) == SET
5043 && !dead_or_set_p (follow, SET_SRC (pat))
5044 && !mep_mentioned_p (PATTERN (follow), SET_SRC (pat), 0)
5045 && !mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 0))
5047 if (dump_file)
5048 fprintf (dump_file, "\tskipping %d\n", INSN_UID (follow));
5049 follow = next_nonnote_insn (follow);
5052 if (dump_file)
5053 fprintf (dump_file, "\tfollow is %d\n", INSN_UID (follow));
5054 if (follow && GET_CODE (follow) == INSN
5055 && GET_CODE (PATTERN (follow)) == SET
5056 && find_regno_note (follow, REG_DEAD, REGNO (SET_DEST (pat))))
5058 if (GET_CODE (SET_DEST (PATTERN (follow))) == REG)
5060 if (mep_mentioned_p (SET_SRC (PATTERN (follow)), SET_DEST (pat), 1))
5062 replace = 1;
5063 where = & SET_SRC (PATTERN (follow));
5066 else if (GET_CODE (SET_DEST (PATTERN (follow))) == MEM)
5068 if (mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 1))
5070 replace = 1;
5071 where = & PATTERN (follow);
5077 /* If so, follow is the corresponding insn */
5078 if (replace)
5080 if (dump_file)
5082 rtx x;
5084 fprintf (dump_file, "----- Candidate for superfluous move deletion:\n\n");
5085 for (x = insn; x ;x = NEXT_INSN (x))
5087 print_rtl_single (dump_file, x);
5088 if (x == follow)
5089 break;
5090 fprintf (dump_file, "\n");
5094 if (validate_replace_rtx_subexp (SET_DEST (pat), SET_SRC (pat),
5095 follow, where))
5097 count ++;
5098 next = delete_insn (insn);
5099 if (dump_file)
5101 fprintf (dump_file, "\n----- Success! new insn:\n\n");
5102 print_rtl_single (dump_file, follow);
5104 done = 0;
5110 if (dump_file)
5112 fprintf (dump_file, "\n%d insn%s deleted out of %d.\n\n", count, count == 1 ? "" : "s", before);
5113 fprintf (dump_file, "=====\n");
5116 #endif
5119 /* Figure out where to put LABEL, which is the label for a repeat loop.
5120 If INCLUDING, LAST_INSN is the last instruction in the loop, otherwise
5121 the loop ends just before LAST_INSN. If SHARED, insns other than the
5122 "repeat" might use LABEL to jump to the loop's continuation point.
5124 Return the last instruction in the adjusted loop. */
5126 static rtx
5127 mep_insert_repeat_label_last (rtx last_insn, rtx label, bool including,
5128 bool shared)
5130 rtx next, prev;
5131 int count = 0, code, icode;
5133 if (dump_file)
5134 fprintf (dump_file, "considering end of repeat loop at insn %d\n",
5135 INSN_UID (last_insn));
5137 /* Set PREV to the last insn in the loop. */
5138 prev = last_insn;
5139 if (!including)
5140 prev = PREV_INSN (prev);
5142 /* Set NEXT to the next insn after the repeat label. */
5143 next = last_insn;
5144 if (!shared)
5145 while (prev != 0)
5147 code = GET_CODE (prev);
5148 if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER)
5149 break;
5151 if (INSN_P (prev))
5153 if (GET_CODE (PATTERN (prev)) == SEQUENCE)
5154 prev = XVECEXP (PATTERN (prev), 0, 1);
5156 /* Other insns that should not be in the last two opcodes. */
5157 icode = recog_memoized (prev);
5158 if (icode < 0
5159 || icode == CODE_FOR_repeat
5160 || icode == CODE_FOR_erepeat
5161 || get_attr_may_trap (prev) == MAY_TRAP_YES)
5162 break;
5164 /* That leaves JUMP_INSN and INSN. It will have BImode if it
5165 is the second instruction in a VLIW bundle. In that case,
5166 loop again: if the first instruction also satisfies the
5167 conditions above then we will reach here again and put
5168 both of them into the repeat epilogue. Otherwise both
5169 should remain outside. */
5170 if (GET_MODE (prev) != BImode)
5172 count++;
5173 next = prev;
5174 if (dump_file)
5175 print_rtl_single (dump_file, next);
5176 if (count == 2)
5177 break;
5180 prev = PREV_INSN (prev);
5183 /* See if we're adding the label immediately after the repeat insn.
5184 If so, we need to separate them with a nop. */
5185 prev = prev_real_insn (next);
5186 if (prev)
5187 switch (recog_memoized (prev))
5189 case CODE_FOR_repeat:
5190 case CODE_FOR_erepeat:
5191 if (dump_file)
5192 fprintf (dump_file, "Adding nop inside loop\n");
5193 emit_insn_before (gen_nop (), next);
5194 break;
5196 default:
5197 break;
5200 /* Insert the label. */
5201 emit_label_before (label, next);
5203 /* Insert the nops. */
5204 if (dump_file && count < 2)
5205 fprintf (dump_file, "Adding %d nop%s\n\n",
5206 2 - count, count == 1 ? "" : "s");
5208 for (; count < 2; count++)
5209 if (including)
5210 last_insn = emit_insn_after (gen_nop (), last_insn);
5211 else
5212 emit_insn_before (gen_nop (), last_insn);
5214 return last_insn;
5218 void
5219 mep_emit_doloop (rtx *operands, int is_end)
5221 rtx tag;
5223 if (cfun->machine->doloop_tags == 0
5224 || cfun->machine->doloop_tag_from_end == is_end)
5226 cfun->machine->doloop_tags++;
5227 cfun->machine->doloop_tag_from_end = is_end;
5230 tag = GEN_INT (cfun->machine->doloop_tags - 1);
5231 if (is_end)
5232 emit_jump_insn (gen_doloop_end_internal (operands[0], operands[4], tag));
5233 else
5234 emit_insn (gen_doloop_begin_internal (operands[0], operands[0], tag));
5238 /* Code for converting doloop_begins and doloop_ends into valid
5239 MeP instructions. A doloop_begin is just a placeholder:
5241 $count = unspec ($count)
5243 where $count is initially the number of iterations - 1.
5244 doloop_end has the form:
5246 if ($count-- == 0) goto label
5248 The counter variable is private to the doloop insns, nothing else
5249 relies on its value.
5251 There are three cases, in decreasing order of preference:
5253 1. A loop has exactly one doloop_begin and one doloop_end.
5254 The doloop_end branches to the first instruction after
5255 the doloop_begin.
5257 In this case we can replace the doloop_begin with a repeat
5258 instruction and remove the doloop_end. I.e.:
5260 $count1 = unspec ($count1)
5261 label:
5263 insn1
5264 insn2
5265 if ($count2-- == 0) goto label
5267 becomes:
5269 repeat $count1,repeat_label
5270 label:
5272 repeat_label:
5273 insn1
5274 insn2
5275 # end repeat
5277 2. As for (1), except there are several doloop_ends. One of them
5278 (call it X) falls through to a label L. All the others fall
5279 through to branches to L.
5281 In this case, we remove X and replace the other doloop_ends
5282 with branches to the repeat label. For example:
5284 $count1 = unspec ($count1)
5285 start:
5287 if ($count2-- == 0) goto label
5288 end:
5290 if ($count3-- == 0) goto label
5291 goto end
5293 becomes:
5295 repeat $count1,repeat_label
5296 start:
5298 repeat_label:
5301 # end repeat
5302 end:
5304 goto repeat_label
5306 3. The fallback case. Replace doloop_begins with:
5308 $count = $count + 1
5310 Replace doloop_ends with the equivalent of:
5312 $count = $count - 1
5313 if ($count == 0) goto label
5315 Note that this might need a scratch register if $count
5316 is stored in memory. */
5318 /* A structure describing one doloop_begin. */
5319 struct mep_doloop_begin {
5320 /* The next doloop_begin with the same tag. */
5321 struct mep_doloop_begin *next;
5323 /* The instruction itself. */
5324 rtx insn;
5326 /* The initial counter value. This is known to be a general register. */
5327 rtx counter;
5330 /* A structure describing a doloop_end. */
5331 struct mep_doloop_end {
5332 /* The next doloop_end with the same loop tag. */
5333 struct mep_doloop_end *next;
5335 /* The instruction itself. */
5336 rtx insn;
5338 /* The first instruction after INSN when the branch isn't taken. */
5339 rtx fallthrough;
5341 /* The location of the counter value. Since doloop_end_internal is a
5342 jump instruction, it has to allow the counter to be stored anywhere
5343 (any non-fixed register or memory location). */
5344 rtx counter;
5346 /* The target label (the place where the insn branches when the counter
5347 isn't zero). */
5348 rtx label;
5350 /* A scratch register. Only available when COUNTER isn't stored
5351 in a general register. */
5352 rtx scratch;
5356 /* One do-while loop. */
5357 struct mep_doloop {
5358 /* All the doloop_begins for this loop (in no particular order). */
5359 struct mep_doloop_begin *begin;
5361 /* All the doloop_ends. When there is more than one, arrange things
5362 so that the first one is the most likely to be X in case (2) above. */
5363 struct mep_doloop_end *end;
5367 /* Return true if LOOP can be converted into repeat/repeat_end form
5368 (that is, if it matches cases (1) or (2) above). */
5370 static bool
5371 mep_repeat_loop_p (struct mep_doloop *loop)
5373 struct mep_doloop_end *end;
5374 rtx fallthrough;
5376 /* There must be exactly one doloop_begin and at least one doloop_end. */
5377 if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0)
5378 return false;
5380 /* The first doloop_end (X) must branch back to the insn after
5381 the doloop_begin. */
5382 if (prev_real_insn (loop->end->label) != loop->begin->insn)
5383 return false;
5385 /* All the other doloop_ends must branch to the same place as X.
5386 When the branch isn't taken, they must jump to the instruction
5387 after X. */
5388 fallthrough = loop->end->fallthrough;
5389 for (end = loop->end->next; end != 0; end = end->next)
5390 if (end->label != loop->end->label
5391 || !simplejump_p (end->fallthrough)
5392 || next_real_insn (JUMP_LABEL (end->fallthrough)) != fallthrough)
5393 return false;
5395 return true;
5399 /* The main repeat reorg function. See comment above for details. */
5401 static void
5402 mep_reorg_repeat (rtx insns)
5404 rtx insn;
5405 struct mep_doloop *loops, *loop;
5406 struct mep_doloop_begin *begin;
5407 struct mep_doloop_end *end;
5409 /* Quick exit if we haven't created any loops. */
5410 if (cfun->machine->doloop_tags == 0)
5411 return;
5413 /* Create an array of mep_doloop structures. */
5414 loops = (struct mep_doloop *) alloca (sizeof (loops[0]) * cfun->machine->doloop_tags);
5415 memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags);
5417 /* Search the function for do-while insns and group them by loop tag. */
5418 for (insn = insns; insn; insn = NEXT_INSN (insn))
5419 if (INSN_P (insn))
5420 switch (recog_memoized (insn))
5422 case CODE_FOR_doloop_begin_internal:
5423 insn_extract (insn);
5424 loop = &loops[INTVAL (recog_data.operand[2])];
5426 begin = (struct mep_doloop_begin *) alloca (sizeof (struct mep_doloop_begin));
5427 begin->next = loop->begin;
5428 begin->insn = insn;
5429 begin->counter = recog_data.operand[0];
5431 loop->begin = begin;
5432 break;
5434 case CODE_FOR_doloop_end_internal:
5435 insn_extract (insn);
5436 loop = &loops[INTVAL (recog_data.operand[2])];
5438 end = (struct mep_doloop_end *) alloca (sizeof (struct mep_doloop_end));
5439 end->insn = insn;
5440 end->fallthrough = next_real_insn (insn);
5441 end->counter = recog_data.operand[0];
5442 end->label = recog_data.operand[1];
5443 end->scratch = recog_data.operand[3];
5445 /* If this insn falls through to an unconditional jump,
5446 give it a lower priority than the others. */
5447 if (loop->end != 0 && simplejump_p (end->fallthrough))
5449 end->next = loop->end->next;
5450 loop->end->next = end;
5452 else
5454 end->next = loop->end;
5455 loop->end = end;
5457 break;
5460 /* Convert the insns for each loop in turn. */
5461 for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++)
5462 if (mep_repeat_loop_p (loop))
5464 /* Case (1) or (2). */
5465 rtx repeat_label, label_ref;
5467 /* Create a new label for the repeat insn. */
5468 repeat_label = gen_label_rtx ();
5470 /* Replace the doloop_begin with a repeat. */
5471 label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label);
5472 emit_insn_before (gen_repeat (loop->begin->counter, label_ref),
5473 loop->begin->insn);
5474 delete_insn (loop->begin->insn);
5476 /* Insert the repeat label before the first doloop_end.
5477 Fill the gap with nops if there are other doloop_ends. */
5478 mep_insert_repeat_label_last (loop->end->insn, repeat_label,
5479 false, loop->end->next != 0);
5481 /* Emit a repeat_end (to improve the readability of the output). */
5482 emit_insn_before (gen_repeat_end (), loop->end->insn);
5484 /* Delete the first doloop_end. */
5485 delete_insn (loop->end->insn);
5487 /* Replace the others with branches to REPEAT_LABEL. */
5488 for (end = loop->end->next; end != 0; end = end->next)
5490 emit_jump_insn_before (gen_jump (repeat_label), end->insn);
5491 delete_insn (end->insn);
5492 delete_insn (end->fallthrough);
5495 else
5497 /* Case (3). First replace all the doloop_begins with increment
5498 instructions. */
5499 for (begin = loop->begin; begin != 0; begin = begin->next)
5501 emit_insn_before (gen_add3_insn (copy_rtx (begin->counter),
5502 begin->counter, const1_rtx),
5503 begin->insn);
5504 delete_insn (begin->insn);
5507 /* Replace all the doloop_ends with decrement-and-branch sequences. */
5508 for (end = loop->end; end != 0; end = end->next)
5510 rtx reg;
5512 start_sequence ();
5514 /* Load the counter value into a general register. */
5515 reg = end->counter;
5516 if (!REG_P (reg) || REGNO (reg) > 15)
5518 reg = end->scratch;
5519 emit_move_insn (copy_rtx (reg), copy_rtx (end->counter));
5522 /* Decrement the counter. */
5523 emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg),
5524 constm1_rtx));
5526 /* Copy it back to its original location. */
5527 if (reg != end->counter)
5528 emit_move_insn (copy_rtx (end->counter), copy_rtx (reg));
5530 /* Jump back to the start label. */
5531 insn = emit_jump_insn (gen_mep_bne_true (reg, const0_rtx,
5532 end->label));
5533 JUMP_LABEL (insn) = end->label;
5534 LABEL_NUSES (end->label)++;
5536 /* Emit the whole sequence before the doloop_end. */
5537 insn = get_insns ();
5538 end_sequence ();
5539 emit_insn_before (insn, end->insn);
5541 /* Delete the doloop_end. */
5542 delete_insn (end->insn);
5548 static bool
5549 mep_invertable_branch_p (rtx insn)
5551 rtx cond, set;
5552 enum rtx_code old_code;
5553 int i;
5555 set = PATTERN (insn);
5556 if (GET_CODE (set) != SET)
5557 return false;
5558 if (GET_CODE (XEXP (set, 1)) != IF_THEN_ELSE)
5559 return false;
5560 cond = XEXP (XEXP (set, 1), 0);
5561 old_code = GET_CODE (cond);
5562 switch (old_code)
5564 case EQ:
5565 PUT_CODE (cond, NE);
5566 break;
5567 case NE:
5568 PUT_CODE (cond, EQ);
5569 break;
5570 case LT:
5571 PUT_CODE (cond, GE);
5572 break;
5573 case GE:
5574 PUT_CODE (cond, LT);
5575 break;
5576 default:
5577 return false;
5579 INSN_CODE (insn) = -1;
5580 i = recog_memoized (insn);
5581 PUT_CODE (cond, old_code);
5582 INSN_CODE (insn) = -1;
5583 return i >= 0;
5586 static void
5587 mep_invert_branch (rtx insn, rtx after)
5589 rtx cond, set, label;
5590 int i;
5592 set = PATTERN (insn);
5594 gcc_assert (GET_CODE (set) == SET);
5595 gcc_assert (GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE);
5597 cond = XEXP (XEXP (set, 1), 0);
5598 switch (GET_CODE (cond))
5600 case EQ:
5601 PUT_CODE (cond, NE);
5602 break;
5603 case NE:
5604 PUT_CODE (cond, EQ);
5605 break;
5606 case LT:
5607 PUT_CODE (cond, GE);
5608 break;
5609 case GE:
5610 PUT_CODE (cond, LT);
5611 break;
5612 default:
5613 gcc_unreachable ();
5615 label = gen_label_rtx ();
5616 emit_label_after (label, after);
5617 for (i=1; i<=2; i++)
5618 if (GET_CODE (XEXP (XEXP (set, 1), i)) == LABEL_REF)
5620 rtx ref = XEXP (XEXP (set, 1), i);
5621 if (LABEL_NUSES (XEXP (ref, 0)) == 1)
5622 delete_insn (XEXP (ref, 0));
5623 XEXP (ref, 0) = label;
5624 LABEL_NUSES (label) ++;
5625 JUMP_LABEL (insn) = label;
5627 INSN_CODE (insn) = -1;
5628 i = recog_memoized (insn);
5629 gcc_assert (i >= 0);
5632 static void
5633 mep_reorg_erepeat (rtx insns)
5635 rtx insn, prev, l, x;
5636 int count;
5638 for (insn = insns; insn; insn = NEXT_INSN (insn))
5639 if (JUMP_P (insn)
5640 && ! JUMP_TABLE_DATA_P (insn)
5641 && mep_invertable_branch_p (insn))
5643 if (dump_file)
5645 fprintf (dump_file, "\n------------------------------\n");
5646 fprintf (dump_file, "erepeat: considering this jump:\n");
5647 print_rtl_single (dump_file, insn);
5649 count = simplejump_p (insn) ? 0 : 1;
5650 for (prev = PREV_INSN (insn); prev; prev = PREV_INSN (prev))
5652 if (GET_CODE (prev) == CALL_INSN
5653 || BARRIER_P (prev))
5654 break;
5656 if (prev == JUMP_LABEL (insn))
5658 rtx newlast;
5659 if (dump_file)
5660 fprintf (dump_file, "found loop top, %d insns\n", count);
5662 if (LABEL_NUSES (prev) == 1)
5663 /* We're the only user, always safe */ ;
5664 else if (LABEL_NUSES (prev) == 2)
5666 /* See if there's a barrier before this label. If
5667 so, we know nobody inside the loop uses it.
5668 But we must be careful to put the erepeat
5669 *after* the label. */
5670 rtx barrier;
5671 for (barrier = PREV_INSN (prev);
5672 barrier && GET_CODE (barrier) == NOTE;
5673 barrier = PREV_INSN (barrier))
5675 if (barrier && GET_CODE (barrier) != BARRIER)
5676 break;
5678 else
5680 /* We don't know who else, within or without our loop, uses this */
5681 if (dump_file)
5682 fprintf (dump_file, "... but there are multiple users, too risky.\n");
5683 break;
5686 /* Generate a label to be used by the erepat insn. */
5687 l = gen_label_rtx ();
5689 /* Insert the erepeat after INSN's target label. */
5690 x = gen_erepeat (gen_rtx_LABEL_REF (VOIDmode, l));
5691 LABEL_NUSES (l)++;
5692 emit_insn_after (x, prev);
5694 /* Insert the erepeat label. */
5695 newlast = (mep_insert_repeat_label_last
5696 (insn, l, !simplejump_p (insn), false));
5697 if (simplejump_p (insn))
5699 emit_insn_before (gen_erepeat_end (), insn);
5700 delete_insn (insn);
5702 else
5704 mep_invert_branch (insn, newlast);
5705 emit_insn_after (gen_erepeat_end (), newlast);
5707 break;
5710 if (LABEL_P (prev))
5712 /* A label is OK if there is exactly one user, and we
5713 can find that user before the next label. */
5714 rtx user = 0;
5715 int safe = 0;
5716 if (LABEL_NUSES (prev) == 1)
5718 for (user = PREV_INSN (prev);
5719 user && (INSN_P (user) || GET_CODE (user) == NOTE);
5720 user = PREV_INSN (user))
5721 if (GET_CODE (user) == JUMP_INSN
5722 && JUMP_LABEL (user) == prev)
5724 safe = INSN_UID (user);
5725 break;
5728 if (!safe)
5729 break;
5730 if (dump_file)
5731 fprintf (dump_file, "... ignoring jump from insn %d to %d\n",
5732 safe, INSN_UID (prev));
5735 if (INSN_P (prev))
5737 count ++;
5741 if (dump_file)
5742 fprintf (dump_file, "\n==============================\n");
5745 /* Replace a jump to a return, with a copy of the return. GCC doesn't
5746 always do this on its own. */
5748 static void
5749 mep_jmp_return_reorg (rtx insns)
5751 rtx insn, label, ret;
5752 int ret_code;
5754 for (insn = insns; insn; insn = NEXT_INSN (insn))
5755 if (simplejump_p (insn))
5757 /* Find the fist real insn the jump jumps to. */
5758 label = ret = JUMP_LABEL (insn);
5759 while (ret
5760 && (GET_CODE (ret) == NOTE
5761 || GET_CODE (ret) == CODE_LABEL
5762 || GET_CODE (PATTERN (ret)) == USE))
5763 ret = NEXT_INSN (ret);
5765 if (ret)
5767 /* Is it a return? */
5768 ret_code = recog_memoized (ret);
5769 if (ret_code == CODE_FOR_return_internal
5770 || ret_code == CODE_FOR_eh_return_internal)
5772 /* It is. Replace the jump with a return. */
5773 LABEL_NUSES (label) --;
5774 if (LABEL_NUSES (label) == 0)
5775 delete_insn (label);
5776 PATTERN (insn) = copy_rtx (PATTERN (ret));
5777 INSN_CODE (insn) = -1;
5784 static void
5785 mep_reorg_addcombine (rtx insns)
5787 rtx i, n;
5789 for (i = insns; i; i = NEXT_INSN (i))
5790 if (INSN_P (i)
5791 && INSN_CODE (i) == CODE_FOR_addsi3
5792 && GET_CODE (SET_DEST (PATTERN (i))) == REG
5793 && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 0)) == REG
5794 && REGNO (SET_DEST (PATTERN (i))) == REGNO (XEXP (SET_SRC (PATTERN (i)), 0))
5795 && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 1)) == CONST_INT)
5797 n = NEXT_INSN (i);
5798 if (INSN_P (n)
5799 && INSN_CODE (n) == CODE_FOR_addsi3
5800 && GET_CODE (SET_DEST (PATTERN (n))) == REG
5801 && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 0)) == REG
5802 && REGNO (SET_DEST (PATTERN (n))) == REGNO (XEXP (SET_SRC (PATTERN (n)), 0))
5803 && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 1)) == CONST_INT)
5805 int ic = INTVAL (XEXP (SET_SRC (PATTERN (i)), 1));
5806 int nc = INTVAL (XEXP (SET_SRC (PATTERN (n)), 1));
5807 if (REGNO (SET_DEST (PATTERN (i))) == REGNO (SET_DEST (PATTERN (n)))
5808 && ic + nc < 32767
5809 && ic + nc > -32768)
5811 XEXP (SET_SRC (PATTERN (i)), 1) = GEN_INT (ic + nc);
5812 NEXT_INSN (i) = NEXT_INSN (n);
5813 if (NEXT_INSN (i))
5814 PREV_INSN (NEXT_INSN (i)) = i;
5820 /* If this insn adjusts the stack, return the adjustment, else return
5821 zero. */
5822 static int
5823 add_sp_insn_p (rtx insn)
5825 rtx pat;
5827 if (! single_set (insn))
5828 return 0;
5829 pat = PATTERN (insn);
5830 if (GET_CODE (SET_DEST (pat)) != REG)
5831 return 0;
5832 if (REGNO (SET_DEST (pat)) != SP_REGNO)
5833 return 0;
5834 if (GET_CODE (SET_SRC (pat)) != PLUS)
5835 return 0;
5836 if (GET_CODE (XEXP (SET_SRC (pat), 0)) != REG)
5837 return 0;
5838 if (REGNO (XEXP (SET_SRC (pat), 0)) != SP_REGNO)
5839 return 0;
5840 if (GET_CODE (XEXP (SET_SRC (pat), 1)) != CONST_INT)
5841 return 0;
5842 return INTVAL (XEXP (SET_SRC (pat), 1));
5845 /* Check for trivial functions that set up an unneeded stack
5846 frame. */
5847 static void
5848 mep_reorg_noframe (rtx insns)
5850 rtx start_frame_insn;
5851 rtx end_frame_insn = 0;
5852 int sp_adjust, sp2;
5853 rtx sp;
5855 /* The first insn should be $sp = $sp + N */
5856 while (insns && ! INSN_P (insns))
5857 insns = NEXT_INSN (insns);
5858 if (!insns)
5859 return;
5861 sp_adjust = add_sp_insn_p (insns);
5862 if (sp_adjust == 0)
5863 return;
5865 start_frame_insn = insns;
5866 sp = SET_DEST (PATTERN (start_frame_insn));
5868 insns = next_real_insn (insns);
5870 while (insns)
5872 rtx next = next_real_insn (insns);
5873 if (!next)
5874 break;
5876 sp2 = add_sp_insn_p (insns);
5877 if (sp2)
5879 if (end_frame_insn)
5880 return;
5881 end_frame_insn = insns;
5882 if (sp2 != -sp_adjust)
5883 return;
5885 else if (mep_mentioned_p (insns, sp, 0))
5886 return;
5887 else if (CALL_P (insns))
5888 return;
5890 insns = next;
5893 if (end_frame_insn)
5895 delete_insn (start_frame_insn);
5896 delete_insn (end_frame_insn);
5900 static void
5901 mep_reorg (void)
5903 rtx insns = get_insns ();
5905 /* We require accurate REG_DEAD notes. */
5906 compute_bb_for_insn ();
5907 df_note_add_problem ();
5908 df_analyze ();
5910 mep_reorg_addcombine (insns);
5911 #if EXPERIMENTAL_REGMOVE_REORG
5912 /* VLIW packing has been done already, so we can't just delete things. */
5913 if (!mep_vliw_function_p (cfun->decl))
5914 mep_reorg_regmove (insns);
5915 #endif
5916 mep_jmp_return_reorg (insns);
5917 mep_bundle_insns (insns);
5918 mep_reorg_repeat (insns);
5919 if (optimize
5920 && !profile_flag
5921 && !profile_arc_flag
5922 && TARGET_OPT_REPEAT
5923 && (!mep_interrupt_p () || mep_interrupt_saved_reg (RPB_REGNO)))
5924 mep_reorg_erepeat (insns);
5926 /* This may delete *insns so make sure it's last. */
5927 mep_reorg_noframe (insns);
5929 df_finish_pass (false);
5934 /*----------------------------------------------------------------------*/
5935 /* Builtins */
5936 /*----------------------------------------------------------------------*/
5938 /* Element X gives the index into cgen_insns[] of the most general
5939 implementation of intrinsic X. Unimplemented intrinsics are
5940 mapped to -1. */
5941 int mep_intrinsic_insn[ARRAY_SIZE (cgen_intrinsics)];
5943 /* Element X gives the index of another instruction that is mapped to
5944 the same intrinsic as cgen_insns[X]. It is -1 when there is no other
5945 instruction.
5947 Things are set up so that mep_intrinsic_chain[X] < X. */
5948 static int mep_intrinsic_chain[ARRAY_SIZE (cgen_insns)];
5950 /* The bitmask for the current ISA. The ISA masks are declared
5951 in mep-intrin.h. */
5952 unsigned int mep_selected_isa;
5954 struct mep_config {
5955 const char *config_name;
5956 unsigned int isa;
5959 static struct mep_config mep_configs[] = {
5960 #ifdef COPROC_SELECTION_TABLE
5961 COPROC_SELECTION_TABLE,
5962 #endif
5963 { 0, 0 }
5966 /* Initialize the global intrinsics variables above. */
5968 static void
5969 mep_init_intrinsics (void)
5971 size_t i;
5973 /* Set MEP_SELECTED_ISA to the ISA flag for this configuration. */
5974 mep_selected_isa = mep_configs[0].isa;
5975 if (mep_config_string != 0)
5976 for (i = 0; mep_configs[i].config_name; i++)
5977 if (strcmp (mep_config_string, mep_configs[i].config_name) == 0)
5979 mep_selected_isa = mep_configs[i].isa;
5980 break;
5983 /* Assume all intrinsics are unavailable. */
5984 for (i = 0; i < ARRAY_SIZE (mep_intrinsic_insn); i++)
5985 mep_intrinsic_insn[i] = -1;
5987 /* Build up the global intrinsic tables. */
5988 for (i = 0; i < ARRAY_SIZE (cgen_insns); i++)
5989 if ((cgen_insns[i].isas & mep_selected_isa) != 0)
5991 mep_intrinsic_chain[i] = mep_intrinsic_insn[cgen_insns[i].intrinsic];
5992 mep_intrinsic_insn[cgen_insns[i].intrinsic] = i;
5994 /* See whether we can directly move values between one coprocessor
5995 register and another. */
5996 for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++)
5997 if (MEP_INTRINSIC_AVAILABLE_P (mep_cmov_insns[i]))
5998 mep_have_copro_copro_moves_p = true;
6000 /* See whether we can directly move values between core and
6001 coprocessor registers. */
6002 mep_have_core_copro_moves_p = (MEP_INTRINSIC_AVAILABLE_P (mep_cmov1)
6003 && MEP_INTRINSIC_AVAILABLE_P (mep_cmov2));
6005 mep_have_core_copro_moves_p = 1;
6008 /* Declare all available intrinsic functions. Called once only. */
6010 static tree cp_data_bus_int_type_node;
6011 static tree opaque_vector_type_node;
6012 static tree v8qi_type_node;
6013 static tree v4hi_type_node;
6014 static tree v2si_type_node;
6015 static tree v8uqi_type_node;
6016 static tree v4uhi_type_node;
6017 static tree v2usi_type_node;
6019 static tree
6020 mep_cgen_regnum_to_type (enum cgen_regnum_operand_type cr)
6022 switch (cr)
6024 case cgen_regnum_operand_type_POINTER: return ptr_type_node;
6025 case cgen_regnum_operand_type_LONG: return long_integer_type_node;
6026 case cgen_regnum_operand_type_ULONG: return long_unsigned_type_node;
6027 case cgen_regnum_operand_type_SHORT: return short_integer_type_node;
6028 case cgen_regnum_operand_type_USHORT: return short_unsigned_type_node;
6029 case cgen_regnum_operand_type_CHAR: return char_type_node;
6030 case cgen_regnum_operand_type_UCHAR: return unsigned_char_type_node;
6031 case cgen_regnum_operand_type_SI: return intSI_type_node;
6032 case cgen_regnum_operand_type_DI: return intDI_type_node;
6033 case cgen_regnum_operand_type_VECTOR: return opaque_vector_type_node;
6034 case cgen_regnum_operand_type_V8QI: return v8qi_type_node;
6035 case cgen_regnum_operand_type_V4HI: return v4hi_type_node;
6036 case cgen_regnum_operand_type_V2SI: return v2si_type_node;
6037 case cgen_regnum_operand_type_V8UQI: return v8uqi_type_node;
6038 case cgen_regnum_operand_type_V4UHI: return v4uhi_type_node;
6039 case cgen_regnum_operand_type_V2USI: return v2usi_type_node;
6040 case cgen_regnum_operand_type_CP_DATA_BUS_INT: return cp_data_bus_int_type_node;
6041 default:
6042 return void_type_node;
6046 static void
6047 mep_init_builtins (void)
6049 size_t i;
6051 if (TARGET_64BIT_CR_REGS)
6052 cp_data_bus_int_type_node = long_long_integer_type_node;
6053 else
6054 cp_data_bus_int_type_node = long_integer_type_node;
6056 opaque_vector_type_node = build_opaque_vector_type (intQI_type_node, 8);
6057 v8qi_type_node = build_vector_type (intQI_type_node, 8);
6058 v4hi_type_node = build_vector_type (intHI_type_node, 4);
6059 v2si_type_node = build_vector_type (intSI_type_node, 2);
6060 v8uqi_type_node = build_vector_type (unsigned_intQI_type_node, 8);
6061 v4uhi_type_node = build_vector_type (unsigned_intHI_type_node, 4);
6062 v2usi_type_node = build_vector_type (unsigned_intSI_type_node, 2);
6064 (*lang_hooks.decls.pushdecl)
6065 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_data_bus_int"),
6066 cp_data_bus_int_type_node));
6068 (*lang_hooks.decls.pushdecl)
6069 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_vector"),
6070 opaque_vector_type_node));
6072 (*lang_hooks.decls.pushdecl)
6073 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v8qi"),
6074 v8qi_type_node));
6075 (*lang_hooks.decls.pushdecl)
6076 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v4hi"),
6077 v4hi_type_node));
6078 (*lang_hooks.decls.pushdecl)
6079 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v2si"),
6080 v2si_type_node));
6082 (*lang_hooks.decls.pushdecl)
6083 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v8uqi"),
6084 v8uqi_type_node));
6085 (*lang_hooks.decls.pushdecl)
6086 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v4uhi"),
6087 v4uhi_type_node));
6088 (*lang_hooks.decls.pushdecl)
6089 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v2usi"),
6090 v2usi_type_node));
6092 /* Intrinsics like mep_cadd3 are implemented with two groups of
6093 instructions, one which uses UNSPECs and one which uses a specific
6094 rtl code such as PLUS. Instructions in the latter group belong
6095 to GROUP_KNOWN_CODE.
6097 In such cases, the intrinsic will have two entries in the global
6098 tables above. The unspec form is accessed using builtin functions
6099 while the specific form is accessed using the mep_* enum in
6100 mep-intrin.h.
6102 The idea is that __cop arithmetic and builtin functions have
6103 different optimization requirements. If mep_cadd3() appears in
6104 the source code, the user will surely except gcc to use cadd3
6105 rather than a work-alike such as add3. However, if the user
6106 just writes "a + b", where a or b are __cop variables, it is
6107 reasonable for gcc to choose a core instruction rather than
6108 cadd3 if it believes that is more optimal. */
6109 for (i = 0; i < ARRAY_SIZE (cgen_insns); i++)
6110 if ((cgen_insns[i].groups & GROUP_KNOWN_CODE) == 0
6111 && mep_intrinsic_insn[cgen_insns[i].intrinsic] >= 0)
6113 tree ret_type = void_type_node;
6114 tree bi_type;
6116 if (i > 0 && cgen_insns[i].intrinsic == cgen_insns[i-1].intrinsic)
6117 continue;
6119 if (cgen_insns[i].cret_p)
6120 ret_type = mep_cgen_regnum_to_type (cgen_insns[i].regnums[0].type);
6122 bi_type = build_function_type_list (ret_type, NULL_TREE);
6123 add_builtin_function (cgen_intrinsics[cgen_insns[i].intrinsic],
6124 bi_type,
6125 cgen_insns[i].intrinsic, BUILT_IN_MD, NULL, NULL);
6129 /* Report the unavailablity of the given intrinsic. */
6131 #if 1
6132 static void
6133 mep_intrinsic_unavailable (int intrinsic)
6135 static int already_reported_p[ARRAY_SIZE (cgen_intrinsics)];
6137 if (already_reported_p[intrinsic])
6138 return;
6140 if (mep_intrinsic_insn[intrinsic] < 0)
6141 error ("coprocessor intrinsic %qs is not available in this configuration",
6142 cgen_intrinsics[intrinsic]);
6143 else if (CGEN_CURRENT_GROUP == GROUP_VLIW)
6144 error ("%qs is not available in VLIW functions",
6145 cgen_intrinsics[intrinsic]);
6146 else
6147 error ("%qs is not available in non-VLIW functions",
6148 cgen_intrinsics[intrinsic]);
6150 already_reported_p[intrinsic] = 1;
6152 #endif
6155 /* See if any implementation of INTRINSIC is available to the
6156 current function. If so, store the most general implementation
6157 in *INSN_PTR and return true. Return false otherwise. */
6159 static bool
6160 mep_get_intrinsic_insn (int intrinsic ATTRIBUTE_UNUSED, const struct cgen_insn **insn_ptr ATTRIBUTE_UNUSED)
6162 int i;
6164 i = mep_intrinsic_insn[intrinsic];
6165 while (i >= 0 && !CGEN_ENABLE_INSN_P (i))
6166 i = mep_intrinsic_chain[i];
6168 if (i >= 0)
6170 *insn_ptr = &cgen_insns[i];
6171 return true;
6173 return false;
6177 /* Like mep_get_intrinsic_insn, but with extra handling for moves.
6178 If INTRINSIC is mep_cmov, but there is no pure CR <- CR move insn,
6179 try using a work-alike instead. In this case, the returned insn
6180 may have three operands rather than two. */
6182 static bool
6183 mep_get_move_insn (int intrinsic, const struct cgen_insn **cgen_insn)
6185 size_t i;
6187 if (intrinsic == mep_cmov)
6189 for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++)
6190 if (mep_get_intrinsic_insn (mep_cmov_insns[i], cgen_insn))
6191 return true;
6192 return false;
6194 return mep_get_intrinsic_insn (intrinsic, cgen_insn);
6198 /* If ARG is a register operand that is the same size as MODE, convert it
6199 to MODE using a subreg. Otherwise return ARG as-is. */
6201 static rtx
6202 mep_convert_arg (enum machine_mode mode, rtx arg)
6204 if (GET_MODE (arg) != mode
6205 && register_operand (arg, VOIDmode)
6206 && GET_MODE_SIZE (GET_MODE (arg)) == GET_MODE_SIZE (mode))
6207 return simplify_gen_subreg (mode, arg, GET_MODE (arg), 0);
6208 return arg;
6212 /* Apply regnum conversions to ARG using the description given by REGNUM.
6213 Return the new argument on success and null on failure. */
6215 static rtx
6216 mep_convert_regnum (const struct cgen_regnum_operand *regnum, rtx arg)
6218 if (regnum->count == 0)
6219 return arg;
6221 if (GET_CODE (arg) != CONST_INT
6222 || INTVAL (arg) < 0
6223 || INTVAL (arg) >= regnum->count)
6224 return 0;
6226 return gen_rtx_REG (SImode, INTVAL (arg) + regnum->base);
6230 /* Try to make intrinsic argument ARG match the given operand.
6231 UNSIGNED_P is true if the argument has an unsigned type. */
6233 static rtx
6234 mep_legitimize_arg (const struct insn_operand_data *operand, rtx arg,
6235 int unsigned_p)
6237 if (GET_CODE (arg) == CONST_INT)
6239 /* CONST_INTs can only be bound to integer operands. */
6240 if (GET_MODE_CLASS (operand->mode) != MODE_INT)
6241 return 0;
6243 else if (GET_CODE (arg) == CONST_DOUBLE)
6244 /* These hold vector constants. */;
6245 else if (GET_MODE_SIZE (GET_MODE (arg)) != GET_MODE_SIZE (operand->mode))
6247 /* If the argument is a different size from what's expected, we must
6248 have a value in the right mode class in order to convert it. */
6249 if (GET_MODE_CLASS (operand->mode) != GET_MODE_CLASS (GET_MODE (arg)))
6250 return 0;
6252 /* If the operand is an rvalue, promote or demote it to match the
6253 operand's size. This might not need extra instructions when
6254 ARG is a register value. */
6255 if (operand->constraint[0] != '=')
6256 arg = convert_to_mode (operand->mode, arg, unsigned_p);
6259 /* If the operand is an lvalue, bind the operand to a new register.
6260 The caller will copy this value into ARG after the main
6261 instruction. By doing this always, we produce slightly more
6262 optimal code. */
6263 /* But not for control registers. */
6264 if (operand->constraint[0] == '='
6265 && (! REG_P (arg)
6266 || ! (CONTROL_REGNO_P (REGNO (arg))
6267 || CCR_REGNO_P (REGNO (arg))
6268 || CR_REGNO_P (REGNO (arg)))
6270 return gen_reg_rtx (operand->mode);
6272 /* Try simple mode punning. */
6273 arg = mep_convert_arg (operand->mode, arg);
6274 if (operand->predicate (arg, operand->mode))
6275 return arg;
6277 /* See if forcing the argument into a register will make it match. */
6278 if (GET_CODE (arg) == CONST_INT || GET_CODE (arg) == CONST_DOUBLE)
6279 arg = force_reg (operand->mode, arg);
6280 else
6281 arg = mep_convert_arg (operand->mode, force_reg (GET_MODE (arg), arg));
6282 if (operand->predicate (arg, operand->mode))
6283 return arg;
6285 return 0;
6289 /* Report that ARG cannot be passed to argument ARGNUM of intrinsic
6290 function FNNAME. OPERAND describes the operand to which ARGNUM
6291 is mapped. */
6293 static void
6294 mep_incompatible_arg (const struct insn_operand_data *operand, rtx arg,
6295 int argnum, tree fnname)
6297 size_t i;
6299 if (GET_CODE (arg) == CONST_INT)
6300 for (i = 0; i < ARRAY_SIZE (cgen_immediate_predicates); i++)
6301 if (operand->predicate == cgen_immediate_predicates[i].predicate)
6303 const struct cgen_immediate_predicate *predicate;
6304 HOST_WIDE_INT argval;
6306 predicate = &cgen_immediate_predicates[i];
6307 argval = INTVAL (arg);
6308 if (argval < predicate->lower || argval >= predicate->upper)
6309 error ("argument %d of %qE must be in the range %d...%d",
6310 argnum, fnname, predicate->lower, predicate->upper - 1);
6311 else
6312 error ("argument %d of %qE must be a multiple of %d",
6313 argnum, fnname, predicate->align);
6314 return;
6317 error ("incompatible type for argument %d of %qE", argnum, fnname);
6320 static rtx
6321 mep_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6322 rtx subtarget ATTRIBUTE_UNUSED,
6323 enum machine_mode mode ATTRIBUTE_UNUSED,
6324 int ignore ATTRIBUTE_UNUSED)
6326 rtx pat, op[10], arg[10];
6327 unsigned int a;
6328 int opindex, unsigned_p[10];
6329 tree fndecl, args;
6330 unsigned int n_args;
6331 tree fnname;
6332 const struct cgen_insn *cgen_insn;
6333 const struct insn_data_d *idata;
6334 unsigned int first_arg = 0;
6335 unsigned int builtin_n_args;
6337 fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6338 fnname = DECL_NAME (fndecl);
6340 /* Find out which instruction we should emit. Note that some coprocessor
6341 intrinsics may only be available in VLIW mode, or only in normal mode. */
6342 if (!mep_get_intrinsic_insn (DECL_FUNCTION_CODE (fndecl), &cgen_insn))
6344 mep_intrinsic_unavailable (DECL_FUNCTION_CODE (fndecl));
6345 return NULL_RTX;
6347 idata = &insn_data[cgen_insn->icode];
6349 builtin_n_args = cgen_insn->num_args;
6351 if (cgen_insn->cret_p)
6353 if (cgen_insn->cret_p > 1)
6354 builtin_n_args ++;
6355 first_arg = 1;
6356 mep_cgen_regnum_to_type (cgen_insn->regnums[0].type);
6357 builtin_n_args --;
6360 /* Evaluate each argument. */
6361 n_args = call_expr_nargs (exp);
6363 if (n_args < builtin_n_args)
6365 error ("too few arguments to %qE", fnname);
6366 return NULL_RTX;
6368 if (n_args > builtin_n_args)
6370 error ("too many arguments to %qE", fnname);
6371 return NULL_RTX;
6374 for (a = first_arg; a < builtin_n_args + first_arg; a++)
6376 tree value;
6378 args = CALL_EXPR_ARG (exp, a - first_arg);
6380 value = args;
6382 #if 0
6383 if (cgen_insn->regnums[a].reference_p)
6385 if (TREE_CODE (value) != ADDR_EXPR)
6387 debug_tree(value);
6388 error ("argument %d of %qE must be an address", a+1, fnname);
6389 return NULL_RTX;
6391 value = TREE_OPERAND (value, 0);
6393 #endif
6395 /* If the argument has been promoted to int, get the unpromoted
6396 value. This is necessary when sub-int memory values are bound
6397 to reference parameters. */
6398 if (TREE_CODE (value) == NOP_EXPR
6399 && TREE_TYPE (value) == integer_type_node
6400 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
6401 && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))
6402 < TYPE_PRECISION (TREE_TYPE (value))))
6403 value = TREE_OPERAND (value, 0);
6405 /* If the argument has been promoted to double, get the unpromoted
6406 SFmode value. This is necessary for FMAX support, for example. */
6407 if (TREE_CODE (value) == NOP_EXPR
6408 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (value))
6409 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
6410 && TYPE_MODE (TREE_TYPE (value)) == DFmode
6411 && TYPE_MODE (TREE_TYPE (TREE_OPERAND (value, 0))) == SFmode)
6412 value = TREE_OPERAND (value, 0);
6414 unsigned_p[a] = TYPE_UNSIGNED (TREE_TYPE (value));
6415 arg[a] = expand_expr (value, NULL, VOIDmode, EXPAND_NORMAL);
6416 arg[a] = mep_convert_regnum (&cgen_insn->regnums[a], arg[a]);
6417 if (cgen_insn->regnums[a].reference_p)
6419 tree pointed_to = TREE_TYPE (TREE_TYPE (value));
6420 enum machine_mode pointed_mode = TYPE_MODE (pointed_to);
6422 arg[a] = gen_rtx_MEM (pointed_mode, arg[a]);
6424 if (arg[a] == 0)
6426 error ("argument %d of %qE must be in the range %d...%d",
6427 a + 1, fnname, 0, cgen_insn->regnums[a].count - 1);
6428 return NULL_RTX;
6432 for (a = 0; a < first_arg; a++)
6434 if (a == 0 && target && GET_MODE (target) == idata->operand[0].mode)
6435 arg[a] = target;
6436 else
6437 arg[a] = gen_reg_rtx (idata->operand[0].mode);
6440 /* Convert the arguments into a form suitable for the intrinsic.
6441 Report an error if this isn't possible. */
6442 for (opindex = 0; opindex < idata->n_operands; opindex++)
6444 a = cgen_insn->op_mapping[opindex];
6445 op[opindex] = mep_legitimize_arg (&idata->operand[opindex],
6446 arg[a], unsigned_p[a]);
6447 if (op[opindex] == 0)
6449 mep_incompatible_arg (&idata->operand[opindex],
6450 arg[a], a + 1 - first_arg, fnname);
6451 return NULL_RTX;
6455 /* Emit the instruction. */
6456 pat = idata->genfun (op[0], op[1], op[2], op[3], op[4],
6457 op[5], op[6], op[7], op[8], op[9]);
6459 if (GET_CODE (pat) == SET
6460 && GET_CODE (SET_DEST (pat)) == PC
6461 && GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
6462 emit_jump_insn (pat);
6463 else
6464 emit_insn (pat);
6466 /* Copy lvalues back to their final locations. */
6467 for (opindex = 0; opindex < idata->n_operands; opindex++)
6468 if (idata->operand[opindex].constraint[0] == '=')
6470 a = cgen_insn->op_mapping[opindex];
6471 if (a >= first_arg)
6473 if (GET_MODE_CLASS (GET_MODE (arg[a]))
6474 != GET_MODE_CLASS (GET_MODE (op[opindex])))
6475 emit_move_insn (arg[a], gen_lowpart (GET_MODE (arg[a]),
6476 op[opindex]));
6477 else
6479 /* First convert the operand to the right mode, then copy it
6480 into the destination. Doing the conversion as a separate
6481 step (rather than using convert_move) means that we can
6482 avoid creating no-op moves when ARG[A] and OP[OPINDEX]
6483 refer to the same register. */
6484 op[opindex] = convert_to_mode (GET_MODE (arg[a]),
6485 op[opindex], unsigned_p[a]);
6486 if (!rtx_equal_p (arg[a], op[opindex]))
6487 emit_move_insn (arg[a], op[opindex]);
6492 if (first_arg > 0 && target && target != op[0])
6494 emit_move_insn (target, op[0]);
6497 return target;
6500 static bool
6501 mep_vector_mode_supported_p (enum machine_mode mode ATTRIBUTE_UNUSED)
6503 return false;
6506 /* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions
6507 a global register. */
6509 static int
6510 global_reg_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6512 int regno;
6513 rtx x = *loc;
6515 if (! x)
6516 return 0;
6518 switch (GET_CODE (x))
6520 case SUBREG:
6521 if (REG_P (SUBREG_REG (x)))
6523 if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
6524 && global_regs[subreg_regno (x)])
6525 return 1;
6526 return 0;
6528 break;
6530 case REG:
6531 regno = REGNO (x);
6532 if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
6533 return 1;
6534 return 0;
6536 case SCRATCH:
6537 case PC:
6538 case CC0:
6539 case CONST_INT:
6540 case CONST_DOUBLE:
6541 case CONST:
6542 case LABEL_REF:
6543 return 0;
6545 case CALL:
6546 /* A non-constant call might use a global register. */
6547 return 1;
6549 default:
6550 break;
6553 return 0;
6556 /* Returns nonzero if X mentions a global register. */
6558 static int
6559 global_reg_mentioned_p (rtx x)
6561 if (INSN_P (x))
6563 if (CALL_P (x))
6565 if (! RTL_CONST_OR_PURE_CALL_P (x))
6566 return 1;
6567 x = CALL_INSN_FUNCTION_USAGE (x);
6568 if (x == 0)
6569 return 0;
6571 else
6572 x = PATTERN (x);
6575 return for_each_rtx (&x, global_reg_mentioned_p_1, NULL);
6577 /* Scheduling hooks for VLIW mode.
6579 Conceptually this is very simple: we have a two-pack architecture
6580 that takes one core insn and one coprocessor insn to make up either
6581 a 32- or 64-bit instruction word (depending on the option bit set in
6582 the chip). I.e. in VL32 mode, we can pack one 16-bit core insn and
6583 one 16-bit cop insn; in VL64 mode we can pack one 16-bit core insn
6584 and one 48-bit cop insn or two 32-bit core/cop insns.
6586 In practice, instruction selection will be a bear. Consider in
6587 VL64 mode the following insns
6589 add $1, 1
6590 cmov $cr0, $0
6592 these cannot pack, since the add is a 16-bit core insn and cmov
6593 is a 32-bit cop insn. However,
6595 add3 $1, $1, 1
6596 cmov $cr0, $0
6598 packs just fine. For good VLIW code generation in VL64 mode, we
6599 will have to have 32-bit alternatives for many of the common core
6600 insns. Not implemented. */
6602 static int
6603 mep_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
6605 int cost_specified;
6607 if (REG_NOTE_KIND (link) != 0)
6609 /* See whether INSN and DEP_INSN are intrinsics that set the same
6610 hard register. If so, it is more important to free up DEP_INSN
6611 than it is to free up INSN.
6613 Note that intrinsics like mep_mulr are handled differently from
6614 the equivalent mep.md patterns. In mep.md, if we don't care
6615 about the value of $lo and $hi, the pattern will just clobber
6616 the registers, not set them. Since clobbers don't count as
6617 output dependencies, it is often possible to reorder two mulrs,
6618 even after reload.
6620 In contrast, mep_mulr() sets both $lo and $hi to specific values,
6621 so any pair of mep_mulr()s will be inter-dependent. We should
6622 therefore give the first mep_mulr() a higher priority. */
6623 if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT
6624 && global_reg_mentioned_p (PATTERN (insn))
6625 && global_reg_mentioned_p (PATTERN (dep_insn)))
6626 return 1;
6628 /* If the dependence is an anti or output dependence, assume it
6629 has no cost. */
6630 return 0;
6633 /* If we can't recognize the insns, we can't really do anything. */
6634 if (recog_memoized (dep_insn) < 0)
6635 return cost;
6637 /* The latency attribute doesn't apply to MeP-h1: we use the stall
6638 attribute instead. */
6639 if (!TARGET_H1)
6641 cost_specified = get_attr_latency (dep_insn);
6642 if (cost_specified != 0)
6643 return cost_specified;
6646 return cost;
6649 /* ??? We don't properly compute the length of a load/store insn,
6650 taking into account the addressing mode. */
6652 static int
6653 mep_issue_rate (void)
6655 return TARGET_IVC2 ? 3 : 2;
6658 /* Return true if function DECL was declared with the vliw attribute. */
6660 bool
6661 mep_vliw_function_p (tree decl)
6663 return lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))) != 0;
6666 static rtx
6667 mep_find_ready_insn (rtx *ready, int nready, enum attr_slot slot, int length)
6669 int i;
6671 for (i = nready - 1; i >= 0; --i)
6673 rtx insn = ready[i];
6674 if (recog_memoized (insn) >= 0
6675 && get_attr_slot (insn) == slot
6676 && get_attr_length (insn) == length)
6677 return insn;
6680 return NULL_RTX;
6683 static void
6684 mep_move_ready_insn (rtx *ready, int nready, rtx insn)
6686 int i;
6688 for (i = 0; i < nready; ++i)
6689 if (ready[i] == insn)
6691 for (; i < nready - 1; ++i)
6692 ready[i] = ready[i + 1];
6693 ready[i] = insn;
6694 return;
6697 gcc_unreachable ();
6700 static void
6701 mep_print_sched_insn (FILE *dump, rtx insn)
6703 const char *slots = "none";
6704 const char *name = NULL;
6705 int code;
6706 char buf[30];
6708 if (GET_CODE (PATTERN (insn)) == SET
6709 || GET_CODE (PATTERN (insn)) == PARALLEL)
6711 switch (get_attr_slots (insn))
6713 case SLOTS_CORE: slots = "core"; break;
6714 case SLOTS_C3: slots = "c3"; break;
6715 case SLOTS_P0: slots = "p0"; break;
6716 case SLOTS_P0_P0S: slots = "p0,p0s"; break;
6717 case SLOTS_P0_P1: slots = "p0,p1"; break;
6718 case SLOTS_P0S: slots = "p0s"; break;
6719 case SLOTS_P0S_P1: slots = "p0s,p1"; break;
6720 case SLOTS_P1: slots = "p1"; break;
6721 default:
6722 sprintf(buf, "%d", get_attr_slots (insn));
6723 slots = buf;
6724 break;
6727 if (GET_CODE (PATTERN (insn)) == USE)
6728 slots = "use";
6730 code = INSN_CODE (insn);
6731 if (code >= 0)
6732 name = get_insn_name (code);
6733 if (!name)
6734 name = "{unknown}";
6736 fprintf (dump,
6737 "insn %4d %4d %8s %s\n",
6738 code,
6739 INSN_UID (insn),
6740 name,
6741 slots);
6744 static int
6745 mep_sched_reorder (FILE *dump ATTRIBUTE_UNUSED,
6746 int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
6747 int *pnready, int clock ATTRIBUTE_UNUSED)
6749 int nready = *pnready;
6750 rtx core_insn, cop_insn;
6751 int i;
6753 if (dump && sched_verbose > 1)
6755 fprintf (dump, "\nsched_reorder: clock %d nready %d\n", clock, nready);
6756 for (i=0; i<nready; i++)
6757 mep_print_sched_insn (dump, ready[i]);
6758 fprintf (dump, "\n");
6761 if (!mep_vliw_function_p (cfun->decl))
6762 return 1;
6763 if (nready < 2)
6764 return 1;
6766 /* IVC2 uses a DFA to determine what's ready and what's not. */
6767 if (TARGET_IVC2)
6768 return nready;
6770 /* We can issue either a core or coprocessor instruction.
6771 Look for a matched pair of insns to reorder. If we don't
6772 find any, don't second-guess the scheduler's priorities. */
6774 if ((core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 2))
6775 && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP,
6776 TARGET_OPT_VL64 ? 6 : 2)))
6778 else if (TARGET_OPT_VL64
6779 && (core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 4))
6780 && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP, 4)))
6782 else
6783 /* We didn't find a pair. Issue the single insn at the head
6784 of the ready list. */
6785 return 1;
6787 /* Reorder the two insns first. */
6788 mep_move_ready_insn (ready, nready, core_insn);
6789 mep_move_ready_insn (ready, nready - 1, cop_insn);
6790 return 2;
6793 /* A for_each_rtx callback. Return true if *X is a register that is
6794 set by insn PREV. */
6796 static int
6797 mep_store_find_set (rtx *x, void *prev)
6799 return REG_P (*x) && reg_set_p (*x, (const_rtx) prev);
6802 /* Like mep_store_bypass_p, but takes a pattern as the second argument,
6803 not the containing insn. */
6805 static bool
6806 mep_store_data_bypass_1 (rtx prev, rtx pat)
6808 /* Cope with intrinsics like swcpa. */
6809 if (GET_CODE (pat) == PARALLEL)
6811 int i;
6813 for (i = 0; i < XVECLEN (pat, 0); i++)
6814 if (mep_store_data_bypass_p (prev, XVECEXP (pat, 0, i)))
6815 return true;
6817 return false;
6820 /* Check for some sort of store. */
6821 if (GET_CODE (pat) != SET
6822 || GET_CODE (SET_DEST (pat)) != MEM)
6823 return false;
6825 /* Intrinsics use patterns of the form (set (mem (scratch)) (unspec ...)).
6826 The first operand to the unspec is the store data and the other operands
6827 are used to calculate the address. */
6828 if (GET_CODE (SET_SRC (pat)) == UNSPEC)
6830 rtx src;
6831 int i;
6833 src = SET_SRC (pat);
6834 for (i = 1; i < XVECLEN (src, 0); i++)
6835 if (for_each_rtx (&XVECEXP (src, 0, i), mep_store_find_set, prev))
6836 return false;
6838 return true;
6841 /* Otherwise just check that PREV doesn't modify any register mentioned
6842 in the memory destination. */
6843 return !for_each_rtx (&SET_DEST (pat), mep_store_find_set, prev);
6846 /* Return true if INSN is a store instruction and if the store address
6847 has no true dependence on PREV. */
6849 bool
6850 mep_store_data_bypass_p (rtx prev, rtx insn)
6852 return INSN_P (insn) ? mep_store_data_bypass_1 (prev, PATTERN (insn)) : false;
6855 /* A for_each_rtx subroutine of mep_mul_hilo_bypass_p. Return 1 if *X
6856 is a register other than LO or HI and if PREV sets *X. */
6858 static int
6859 mep_mul_hilo_bypass_1 (rtx *x, void *prev)
6861 return (REG_P (*x)
6862 && REGNO (*x) != LO_REGNO
6863 && REGNO (*x) != HI_REGNO
6864 && reg_set_p (*x, (const_rtx) prev));
6867 /* Return true if, apart from HI/LO, there are no true dependencies
6868 between multiplication instructions PREV and INSN. */
6870 bool
6871 mep_mul_hilo_bypass_p (rtx prev, rtx insn)
6873 rtx pat;
6875 pat = PATTERN (insn);
6876 if (GET_CODE (pat) == PARALLEL)
6877 pat = XVECEXP (pat, 0, 0);
6878 return (GET_CODE (pat) == SET
6879 && !for_each_rtx (&SET_SRC (pat), mep_mul_hilo_bypass_1, prev));
6882 /* Return true if INSN is an ldc instruction that issues to the
6883 MeP-h1 integer pipeline. This is true for instructions that
6884 read from PSW, LP, SAR, HI and LO. */
6886 bool
6887 mep_ipipe_ldc_p (rtx insn)
6889 rtx pat, src;
6891 pat = PATTERN (insn);
6893 /* Cope with instrinsics that set both a hard register and its shadow.
6894 The set of the hard register comes first. */
6895 if (GET_CODE (pat) == PARALLEL)
6896 pat = XVECEXP (pat, 0, 0);
6898 if (GET_CODE (pat) == SET)
6900 src = SET_SRC (pat);
6902 /* Cope with intrinsics. The first operand to the unspec is
6903 the source register. */
6904 if (GET_CODE (src) == UNSPEC || GET_CODE (src) == UNSPEC_VOLATILE)
6905 src = XVECEXP (src, 0, 0);
6907 if (REG_P (src))
6908 switch (REGNO (src))
6910 case PSW_REGNO:
6911 case LP_REGNO:
6912 case SAR_REGNO:
6913 case HI_REGNO:
6914 case LO_REGNO:
6915 return true;
6918 return false;
6921 /* Create a VLIW bundle from core instruction CORE and coprocessor
6922 instruction COP. COP always satisfies INSN_P, but CORE can be
6923 either a new pattern or an existing instruction.
6925 Emit the bundle in place of COP and return it. */
6927 static rtx
6928 mep_make_bundle (rtx core, rtx cop)
6930 rtx insn;
6932 /* If CORE is an existing instruction, remove it, otherwise put
6933 the new pattern in an INSN harness. */
6934 if (INSN_P (core))
6935 remove_insn (core);
6936 else
6937 core = make_insn_raw (core);
6939 /* Generate the bundle sequence and replace COP with it. */
6940 insn = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (2, core, cop));
6941 insn = emit_insn_after (insn, cop);
6942 remove_insn (cop);
6944 /* Set up the links of the insns inside the SEQUENCE. */
6945 PREV_INSN (core) = PREV_INSN (insn);
6946 NEXT_INSN (core) = cop;
6947 PREV_INSN (cop) = core;
6948 NEXT_INSN (cop) = NEXT_INSN (insn);
6950 /* Set the VLIW flag for the coprocessor instruction. */
6951 PUT_MODE (core, VOIDmode);
6952 PUT_MODE (cop, BImode);
6954 /* Derive a location for the bundle. Individual instructions cannot
6955 have their own location because there can be no assembler labels
6956 between CORE and COP. */
6957 INSN_LOCATOR (insn) = INSN_LOCATOR (INSN_LOCATOR (core) ? core : cop);
6958 INSN_LOCATOR (core) = 0;
6959 INSN_LOCATOR (cop) = 0;
6961 return insn;
6964 /* A helper routine for ms1_insn_dependent_p called through note_stores. */
6966 static void
6967 mep_insn_dependent_p_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
6969 rtx * pinsn = (rtx *) data;
6971 if (*pinsn && reg_mentioned_p (x, *pinsn))
6972 *pinsn = NULL_RTX;
6975 /* Return true if anything in insn X is (anti,output,true) dependent on
6976 anything in insn Y. */
6978 static int
6979 mep_insn_dependent_p (rtx x, rtx y)
6981 rtx tmp;
6983 gcc_assert (INSN_P (x));
6984 gcc_assert (INSN_P (y));
6986 tmp = PATTERN (y);
6987 note_stores (PATTERN (x), mep_insn_dependent_p_1, &tmp);
6988 if (tmp == NULL_RTX)
6989 return 1;
6991 tmp = PATTERN (x);
6992 note_stores (PATTERN (y), mep_insn_dependent_p_1, &tmp);
6993 if (tmp == NULL_RTX)
6994 return 1;
6996 return 0;
6999 static int
7000 core_insn_p (rtx insn)
7002 if (GET_CODE (PATTERN (insn)) == USE)
7003 return 0;
7004 if (get_attr_slot (insn) == SLOT_CORE)
7005 return 1;
7006 return 0;
7009 /* Mark coprocessor instructions that can be bundled together with
7010 the immediately preceeding core instruction. This is later used
7011 to emit the "+" that tells the assembler to create a VLIW insn.
7013 For unbundled insns, the assembler will automatically add coprocessor
7014 nops, and 16-bit core nops. Due to an apparent oversight in the
7015 spec, the assembler will _not_ automatically add 32-bit core nops,
7016 so we have to emit those here.
7018 Called from mep_insn_reorg. */
7020 static void
7021 mep_bundle_insns (rtx insns)
7023 rtx insn, last = NULL_RTX, first = NULL_RTX;
7024 int saw_scheduling = 0;
7026 /* Only do bundling if we're in vliw mode. */
7027 if (!mep_vliw_function_p (cfun->decl))
7028 return;
7030 /* The first insn in a bundle are TImode, the remainder are
7031 VOIDmode. After this function, the first has VOIDmode and the
7032 rest have BImode. */
7034 /* Note: this doesn't appear to be true for JUMP_INSNs. */
7036 /* First, move any NOTEs that are within a bundle, to the beginning
7037 of the bundle. */
7038 for (insn = insns; insn ; insn = NEXT_INSN (insn))
7040 if (NOTE_P (insn) && first)
7041 /* Don't clear FIRST. */;
7043 else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == TImode)
7044 first = insn;
7046 else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == VOIDmode && first)
7048 rtx note, prev;
7050 /* INSN is part of a bundle; FIRST is the first insn in that
7051 bundle. Move all intervening notes out of the bundle.
7052 In addition, since the debug pass may insert a label
7053 whenever the current line changes, set the location info
7054 for INSN to match FIRST. */
7056 INSN_LOCATOR (insn) = INSN_LOCATOR (first);
7058 note = PREV_INSN (insn);
7059 while (note && note != first)
7061 prev = PREV_INSN (note);
7063 if (NOTE_P (note))
7065 /* Remove NOTE from here... */
7066 PREV_INSN (NEXT_INSN (note)) = PREV_INSN (note);
7067 NEXT_INSN (PREV_INSN (note)) = NEXT_INSN (note);
7068 /* ...and put it in here. */
7069 NEXT_INSN (note) = first;
7070 PREV_INSN (note) = PREV_INSN (first);
7071 NEXT_INSN (PREV_INSN (note)) = note;
7072 PREV_INSN (NEXT_INSN (note)) = note;
7075 note = prev;
7079 else if (!NONJUMP_INSN_P (insn))
7080 first = 0;
7083 /* Now fix up the bundles. */
7084 for (insn = insns; insn ; insn = NEXT_INSN (insn))
7086 if (NOTE_P (insn))
7087 continue;
7089 if (!NONJUMP_INSN_P (insn))
7091 last = 0;
7092 continue;
7095 /* If we're not optimizing enough, there won't be scheduling
7096 info. We detect that here. */
7097 if (GET_MODE (insn) == TImode)
7098 saw_scheduling = 1;
7099 if (!saw_scheduling)
7100 continue;
7102 if (TARGET_IVC2)
7104 rtx core_insn = NULL_RTX;
7106 /* IVC2 slots are scheduled by DFA, so we just accept
7107 whatever the scheduler gives us. However, we must make
7108 sure the core insn (if any) is the first in the bundle.
7109 The IVC2 assembler can insert whatever NOPs are needed,
7110 and allows a COP insn to be first. */
7112 if (NONJUMP_INSN_P (insn)
7113 && GET_CODE (PATTERN (insn)) != USE
7114 && GET_MODE (insn) == TImode)
7116 for (last = insn;
7117 NEXT_INSN (last)
7118 && GET_MODE (NEXT_INSN (last)) == VOIDmode
7119 && NONJUMP_INSN_P (NEXT_INSN (last));
7120 last = NEXT_INSN (last))
7122 if (core_insn_p (last))
7123 core_insn = last;
7125 if (core_insn_p (last))
7126 core_insn = last;
7128 if (core_insn && core_insn != insn)
7130 /* Swap core insn to first in the bundle. */
7132 /* Remove core insn. */
7133 if (PREV_INSN (core_insn))
7134 NEXT_INSN (PREV_INSN (core_insn)) = NEXT_INSN (core_insn);
7135 if (NEXT_INSN (core_insn))
7136 PREV_INSN (NEXT_INSN (core_insn)) = PREV_INSN (core_insn);
7138 /* Re-insert core insn. */
7139 PREV_INSN (core_insn) = PREV_INSN (insn);
7140 NEXT_INSN (core_insn) = insn;
7142 if (PREV_INSN (core_insn))
7143 NEXT_INSN (PREV_INSN (core_insn)) = core_insn;
7144 PREV_INSN (insn) = core_insn;
7146 PUT_MODE (core_insn, TImode);
7147 PUT_MODE (insn, VOIDmode);
7151 /* The first insn has TImode, the rest have VOIDmode */
7152 if (GET_MODE (insn) == TImode)
7153 PUT_MODE (insn, VOIDmode);
7154 else
7155 PUT_MODE (insn, BImode);
7156 continue;
7159 PUT_MODE (insn, VOIDmode);
7160 if (recog_memoized (insn) >= 0
7161 && get_attr_slot (insn) == SLOT_COP)
7163 if (GET_CODE (insn) == JUMP_INSN
7164 || ! last
7165 || recog_memoized (last) < 0
7166 || get_attr_slot (last) != SLOT_CORE
7167 || (get_attr_length (insn)
7168 != (TARGET_OPT_VL64 ? 8 : 4) - get_attr_length (last))
7169 || mep_insn_dependent_p (insn, last))
7171 switch (get_attr_length (insn))
7173 case 8:
7174 break;
7175 case 6:
7176 insn = mep_make_bundle (gen_nop (), insn);
7177 break;
7178 case 4:
7179 if (TARGET_OPT_VL64)
7180 insn = mep_make_bundle (gen_nop32 (), insn);
7181 break;
7182 case 2:
7183 if (TARGET_OPT_VL64)
7184 error ("2 byte cop instructions are"
7185 " not allowed in 64-bit VLIW mode");
7186 else
7187 insn = mep_make_bundle (gen_nop (), insn);
7188 break;
7189 default:
7190 error ("unexpected %d byte cop instruction",
7191 get_attr_length (insn));
7192 break;
7195 else
7196 insn = mep_make_bundle (last, insn);
7199 last = insn;
7204 /* Try to instantiate INTRINSIC with the operands given in OPERANDS.
7205 Return true on success. This function can fail if the intrinsic
7206 is unavailable or if the operands don't satisfy their predicates. */
7208 bool
7209 mep_emit_intrinsic (int intrinsic, const rtx *operands)
7211 const struct cgen_insn *cgen_insn;
7212 const struct insn_data_d *idata;
7213 rtx newop[10];
7214 int i;
7216 if (!mep_get_intrinsic_insn (intrinsic, &cgen_insn))
7217 return false;
7219 idata = &insn_data[cgen_insn->icode];
7220 for (i = 0; i < idata->n_operands; i++)
7222 newop[i] = mep_convert_arg (idata->operand[i].mode, operands[i]);
7223 if (!idata->operand[i].predicate (newop[i], idata->operand[i].mode))
7224 return false;
7227 emit_insn (idata->genfun (newop[0], newop[1], newop[2],
7228 newop[3], newop[4], newop[5],
7229 newop[6], newop[7], newop[8]));
7231 return true;
7235 /* Apply the given unary intrinsic to OPERANDS[1] and store it on
7236 OPERANDS[0]. Report an error if the instruction could not
7237 be synthesized. OPERANDS[1] is a register_operand. For sign
7238 and zero extensions, it may be smaller than SImode. */
7240 bool
7241 mep_expand_unary_intrinsic (int ATTRIBUTE_UNUSED intrinsic,
7242 rtx * operands ATTRIBUTE_UNUSED)
7244 return false;
7248 /* Likewise, but apply a binary operation to OPERANDS[1] and
7249 OPERANDS[2]. OPERANDS[1] is a register_operand, OPERANDS[2]
7250 can be a general_operand.
7252 IMMEDIATE and IMMEDIATE3 are intrinsics that take an immediate
7253 third operand. REG and REG3 take register operands only. */
7255 bool
7256 mep_expand_binary_intrinsic (int ATTRIBUTE_UNUSED immediate,
7257 int ATTRIBUTE_UNUSED immediate3,
7258 int ATTRIBUTE_UNUSED reg,
7259 int ATTRIBUTE_UNUSED reg3,
7260 rtx * operands ATTRIBUTE_UNUSED)
7262 return false;
7265 static bool
7266 mep_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, bool ATTRIBUTE_UNUSED speed_t)
7268 switch (code)
7270 case CONST_INT:
7271 if (INTVAL (x) >= -128 && INTVAL (x) < 127)
7272 *total = 0;
7273 else if (INTVAL (x) >= -32768 && INTVAL (x) < 65536)
7274 *total = 1;
7275 else
7276 *total = 3;
7277 return true;
7279 case SYMBOL_REF:
7280 *total = optimize_size ? COSTS_N_INSNS (0) : COSTS_N_INSNS (1);
7281 return true;
7283 case MULT:
7284 *total = (GET_CODE (XEXP (x, 1)) == CONST_INT
7285 ? COSTS_N_INSNS (3)
7286 : COSTS_N_INSNS (2));
7287 return true;
7289 return false;
7292 static int
7293 mep_address_cost (rtx addr ATTRIBUTE_UNUSED, bool ATTRIBUTE_UNUSED speed_p)
7295 return 1;
7298 static void
7299 mep_asm_init_sections (void)
7301 based_section
7302 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7303 "\t.section .based,\"aw\"");
7305 tinybss_section
7306 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op,
7307 "\t.section .sbss,\"aw\"");
7309 sdata_section
7310 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7311 "\t.section .sdata,\"aw\",@progbits");
7313 far_section
7314 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
7315 "\t.section .far,\"aw\"");
7317 farbss_section
7318 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op,
7319 "\t.section .farbss,\"aw\"");
7321 frodata_section
7322 = get_unnamed_section (0, output_section_asm_op,
7323 "\t.section .frodata,\"a\"");
7325 srodata_section
7326 = get_unnamed_section (0, output_section_asm_op,
7327 "\t.section .srodata,\"a\"");
7329 vtext_section
7330 = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op,
7331 "\t.section .vtext,\"axv\"\n\t.vliw");
7333 vftext_section
7334 = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op,
7335 "\t.section .vftext,\"axv\"\n\t.vliw");
7337 ftext_section
7338 = get_unnamed_section (SECTION_CODE, output_section_asm_op,
7339 "\t.section .ftext,\"ax\"\n\t.core");
7343 /* Initialize the GCC target structure. */
7345 #undef TARGET_ASM_FUNCTION_PROLOGUE
7346 #define TARGET_ASM_FUNCTION_PROLOGUE mep_start_function
7347 #undef TARGET_ATTRIBUTE_TABLE
7348 #define TARGET_ATTRIBUTE_TABLE mep_attribute_table
7349 #undef TARGET_COMP_TYPE_ATTRIBUTES
7350 #define TARGET_COMP_TYPE_ATTRIBUTES mep_comp_type_attributes
7351 #undef TARGET_INSERT_ATTRIBUTES
7352 #define TARGET_INSERT_ATTRIBUTES mep_insert_attributes
7353 #undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
7354 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P mep_function_attribute_inlinable_p
7355 #undef TARGET_CAN_INLINE_P
7356 #define TARGET_CAN_INLINE_P mep_can_inline_p
7357 #undef TARGET_SECTION_TYPE_FLAGS
7358 #define TARGET_SECTION_TYPE_FLAGS mep_section_type_flags
7359 #undef TARGET_ASM_NAMED_SECTION
7360 #define TARGET_ASM_NAMED_SECTION mep_asm_named_section
7361 #undef TARGET_INIT_BUILTINS
7362 #define TARGET_INIT_BUILTINS mep_init_builtins
7363 #undef TARGET_EXPAND_BUILTIN
7364 #define TARGET_EXPAND_BUILTIN mep_expand_builtin
7365 #undef TARGET_SCHED_ADJUST_COST
7366 #define TARGET_SCHED_ADJUST_COST mep_adjust_cost
7367 #undef TARGET_SCHED_ISSUE_RATE
7368 #define TARGET_SCHED_ISSUE_RATE mep_issue_rate
7369 #undef TARGET_SCHED_REORDER
7370 #define TARGET_SCHED_REORDER mep_sched_reorder
7371 #undef TARGET_STRIP_NAME_ENCODING
7372 #define TARGET_STRIP_NAME_ENCODING mep_strip_name_encoding
7373 #undef TARGET_ASM_SELECT_SECTION
7374 #define TARGET_ASM_SELECT_SECTION mep_select_section
7375 #undef TARGET_ASM_UNIQUE_SECTION
7376 #define TARGET_ASM_UNIQUE_SECTION mep_unique_section
7377 #undef TARGET_ENCODE_SECTION_INFO
7378 #define TARGET_ENCODE_SECTION_INFO mep_encode_section_info
7379 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
7380 #define TARGET_FUNCTION_OK_FOR_SIBCALL mep_function_ok_for_sibcall
7381 #undef TARGET_RTX_COSTS
7382 #define TARGET_RTX_COSTS mep_rtx_cost
7383 #undef TARGET_ADDRESS_COST
7384 #define TARGET_ADDRESS_COST mep_address_cost
7385 #undef TARGET_MACHINE_DEPENDENT_REORG
7386 #define TARGET_MACHINE_DEPENDENT_REORG mep_reorg
7387 #undef TARGET_SETUP_INCOMING_VARARGS
7388 #define TARGET_SETUP_INCOMING_VARARGS mep_setup_incoming_varargs
7389 #undef TARGET_PASS_BY_REFERENCE
7390 #define TARGET_PASS_BY_REFERENCE mep_pass_by_reference
7391 #undef TARGET_FUNCTION_ARG
7392 #define TARGET_FUNCTION_ARG mep_function_arg
7393 #undef TARGET_FUNCTION_ARG_ADVANCE
7394 #define TARGET_FUNCTION_ARG_ADVANCE mep_function_arg_advance
7395 #undef TARGET_VECTOR_MODE_SUPPORTED_P
7396 #define TARGET_VECTOR_MODE_SUPPORTED_P mep_vector_mode_supported_p
7397 #undef TARGET_OPTION_OVERRIDE
7398 #define TARGET_OPTION_OVERRIDE mep_option_override
7399 #undef TARGET_ALLOCATE_INITIAL_VALUE
7400 #define TARGET_ALLOCATE_INITIAL_VALUE mep_allocate_initial_value
7401 #undef TARGET_ASM_INIT_SECTIONS
7402 #define TARGET_ASM_INIT_SECTIONS mep_asm_init_sections
7403 #undef TARGET_RETURN_IN_MEMORY
7404 #define TARGET_RETURN_IN_MEMORY mep_return_in_memory
7405 #undef TARGET_NARROW_VOLATILE_BITFIELD
7406 #define TARGET_NARROW_VOLATILE_BITFIELD mep_narrow_volatile_bitfield
7407 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
7408 #define TARGET_EXPAND_BUILTIN_SAVEREGS mep_expand_builtin_saveregs
7409 #undef TARGET_BUILD_BUILTIN_VA_LIST
7410 #define TARGET_BUILD_BUILTIN_VA_LIST mep_build_builtin_va_list
7411 #undef TARGET_EXPAND_BUILTIN_VA_START
7412 #define TARGET_EXPAND_BUILTIN_VA_START mep_expand_va_start
7413 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
7414 #define TARGET_GIMPLIFY_VA_ARG_EXPR mep_gimplify_va_arg_expr
7415 #undef TARGET_CAN_ELIMINATE
7416 #define TARGET_CAN_ELIMINATE mep_can_eliminate
7417 #undef TARGET_CONDITIONAL_REGISTER_USAGE
7418 #define TARGET_CONDITIONAL_REGISTER_USAGE mep_conditional_register_usage
7419 #undef TARGET_TRAMPOLINE_INIT
7420 #define TARGET_TRAMPOLINE_INIT mep_trampoline_init
7421 #undef TARGET_LEGITIMATE_CONSTANT_P
7422 #define TARGET_LEGITIMATE_CONSTANT_P mep_legitimate_constant_p
7424 struct gcc_target targetm = TARGET_INITIALIZER;
7426 #include "gt-mep.h"