OSDN Git Service

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