OSDN Git Service

efed4b6caf6efdedeb93238b0c4bb6360a4236ee
[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
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 "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "recog.h"
38 #include "obstack.h"
39 #include "tree.h"
40 #include "expr.h"
41 #include "except.h"
42 #include "function.h"
43 #include "optabs.h"
44 #include "reload.h"
45 #include "tm_p.h"
46 #include "ggc.h"
47 #include "toplev.h"
48 #include "integrate.h"
49 #include "target.h"
50 #include "target-def.h"
51 #include "langhooks.h"
52 #include "df.h"
53
54 /* Structure of this file:
55
56  + Command Line Option Support
57  + Pattern support - constraints, predicates, expanders
58  + Reload Support
59  + Costs
60  + Functions to save and restore machine-specific function data.
61  + Frame/Epilog/Prolog Related
62  + Operand Printing
63  + Function args in registers
64  + Handle pipeline hazards
65  + Handle attributes
66  + Trampolines
67  + Machine-dependent Reorg
68  + Builtins.  */
69
70 /* Symbol encodings:
71
72    Symbols are encoded as @ <char> . <name> where <char> is one of these:
73
74    b - based
75    t - tiny
76    n - near
77    f - far
78    i - io, near
79    I - io, far
80    c - cb (control bus)  */
81
82 struct GTY(()) machine_function
83 {
84   int mep_frame_pointer_needed;
85   
86   /* For varargs. */
87   int arg_regs_to_save;
88   int regsave_filler;
89   int frame_filler;
90   int frame_locked;
91   
92   /* Records __builtin_return address.  */
93   rtx eh_stack_adjust;
94   
95   int reg_save_size;
96   int reg_save_slot[FIRST_PSEUDO_REGISTER];
97   unsigned char reg_saved[FIRST_PSEUDO_REGISTER];
98   
99   /* 2 if the current function has an interrupt attribute, 1 if not, 0
100      if unknown.  This is here because resource.c uses EPILOGUE_USES
101      which needs it.  */
102   int interrupt_handler;
103   
104   /* Likewise, for disinterrupt attribute.  */
105   int disable_interrupts;
106
107   /* Number of doloop tags used so far.  */
108   int doloop_tags;
109
110   /* True if the last tag was allocated to a doloop_end.  */
111   bool doloop_tag_from_end;
112
113   /* True if reload changes $TP.  */
114   bool reload_changes_tp;
115
116   /* 2 if there are asm()s without operands, 1 if not, 0 if unknown.
117      We only set this if the function is an interrupt handler.  */
118   int asms_without_operands;
119 };
120
121 #define MEP_CONTROL_REG(x) \
122   (GET_CODE (x) == REG && ANY_CONTROL_REGNO_P (REGNO (x)))
123
124 static const struct attribute_spec mep_attribute_table[11];
125
126 static GTY(()) section * based_section;
127 static GTY(()) section * tinybss_section;
128 static GTY(()) section * far_section;
129 static GTY(()) section * farbss_section;
130 static GTY(()) section * frodata_section;
131 static GTY(()) section * srodata_section;
132
133 static GTY(()) section * vtext_section;
134 static GTY(()) section * vftext_section;
135 static GTY(()) section * ftext_section;
136
137 static void mep_set_leaf_registers (int);
138 static bool symbol_p (rtx);
139 static bool symbolref_p (rtx);
140 static void encode_pattern_1 (rtx);
141 static void encode_pattern (rtx);
142 static bool const_in_range (rtx, int, int);
143 static void mep_rewrite_mult (rtx, rtx);
144 static void mep_rewrite_mulsi3 (rtx, rtx, rtx, rtx);
145 static void mep_rewrite_maddsi3 (rtx, rtx, rtx, rtx, rtx);
146 static bool mep_reuse_lo_p_1 (rtx, rtx, rtx, bool);
147 static bool move_needs_splitting (rtx, rtx, enum machine_mode);
148 static bool mep_expand_setcc_1 (enum rtx_code, rtx, rtx, rtx);
149 static bool mep_nongeneral_reg (rtx);
150 static bool mep_general_copro_reg (rtx);
151 static bool mep_nonregister (rtx);
152 static struct machine_function* mep_init_machine_status (void);
153 static rtx mep_tp_rtx (void);
154 static rtx mep_gp_rtx (void);
155 static bool mep_interrupt_p (void);
156 static bool mep_disinterrupt_p (void);
157 static bool mep_reg_set_p (rtx, rtx);
158 static bool mep_reg_set_in_function (int);
159 static bool mep_interrupt_saved_reg (int);
160 static bool mep_call_saves_register (int);
161 static rtx F (rtx);
162 static void add_constant (int, int, int, int);
163 static bool mep_function_uses_sp (void);
164 static rtx maybe_dead_move (rtx, rtx, bool);
165 static void mep_reload_pointer (int, const char *);
166 static void mep_start_function (FILE *, HOST_WIDE_INT);
167 static bool mep_function_ok_for_sibcall (tree, tree);
168 static int unique_bit_in (HOST_WIDE_INT);
169 static int bit_size_for_clip (HOST_WIDE_INT);
170 static int bytesize (const_tree, enum machine_mode);
171 static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *);
172 static tree mep_validate_near_far (tree *, tree, tree, int, bool *);
173 static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *);
174 static tree mep_validate_interrupt (tree *, tree, tree, int, bool *);
175 static tree mep_validate_io_cb (tree *, tree, tree, int, bool *);
176 static tree mep_validate_vliw (tree *, tree, tree, int, bool *);
177 static bool mep_function_attribute_inlinable_p (const_tree);
178 static bool mep_can_inline_p (tree, tree);
179 static bool mep_lookup_pragma_disinterrupt (const char *);
180 static int mep_multiple_address_regions (tree, bool);
181 static int mep_attrlist_to_encoding (tree, tree);
182 static void mep_insert_attributes (tree, tree *);
183 static void mep_encode_section_info (tree, rtx, int);
184 static section * mep_select_section (tree, int, unsigned HOST_WIDE_INT);
185 static void mep_unique_section (tree, int);
186 static unsigned int mep_section_type_flags (tree, const char *, int);
187 static void mep_asm_named_section (const char *, unsigned int, tree);
188 static bool mep_mentioned_p (rtx, rtx, int);
189 static void mep_reorg_regmove (rtx);
190 static rtx mep_insert_repeat_label_last (rtx, rtx, bool, bool);
191 static void mep_reorg_repeat (rtx);
192 static bool mep_invertable_branch_p (rtx);
193 static void mep_invert_branch (rtx, rtx);
194 static void mep_reorg_erepeat (rtx);
195 static void mep_jmp_return_reorg (rtx);
196 static void mep_reorg_addcombine (rtx);
197 static void mep_reorg (void);
198 static void mep_init_intrinsics (void);
199 static void mep_init_builtins (void);
200 static void mep_intrinsic_unavailable (int);
201 static bool mep_get_intrinsic_insn (int, const struct cgen_insn **);
202 static bool mep_get_move_insn (int, const struct cgen_insn **);
203 static rtx mep_convert_arg (enum machine_mode, rtx);
204 static rtx mep_convert_regnum (const struct cgen_regnum_operand *, rtx);
205 static rtx mep_legitimize_arg (const struct insn_operand_data *, rtx, int);
206 static void mep_incompatible_arg (const struct insn_operand_data *, rtx, int, tree);
207 static rtx mep_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
208 static int mep_adjust_cost (rtx, rtx, rtx, int);
209 static int mep_issue_rate (void);
210 static rtx mep_find_ready_insn (rtx *, int, enum attr_slot, int);
211 static void mep_move_ready_insn (rtx *, int, rtx);
212 static int mep_sched_reorder (FILE *, int, rtx *, int *, int);
213 static rtx mep_make_bundle (rtx, rtx);
214 static void mep_bundle_insns (rtx);
215 static bool mep_rtx_cost (rtx, int, int, int *, bool);
216 static int mep_address_cost (rtx, bool);
217 static void mep_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
218                                         tree, int *, int);
219 static bool mep_pass_by_reference (CUMULATIVE_ARGS * cum, enum machine_mode,
220                                    const_tree, bool);
221 static bool mep_vector_mode_supported_p (enum machine_mode);
222 static bool mep_handle_option (size_t, const char *, int);
223 static rtx  mep_allocate_initial_value (rtx);
224 static void mep_asm_init_sections (void);
225 static int mep_comp_type_attributes (const_tree, const_tree);
226 static bool mep_narrow_volatile_bitfield (void);
227 static rtx mep_expand_builtin_saveregs (void);
228 static tree mep_build_builtin_va_list (void);
229 static void mep_expand_va_start (tree, rtx);
230 static tree mep_gimplify_va_arg_expr (tree, tree, tree *, tree *);
231 static bool mep_can_eliminate (const int, const int);
232 \f
233 /* Initialize the GCC target structure.  */
234
235 #undef  TARGET_ASM_FUNCTION_PROLOGUE
236 #define TARGET_ASM_FUNCTION_PROLOGUE    mep_start_function
237 #undef  TARGET_ATTRIBUTE_TABLE
238 #define TARGET_ATTRIBUTE_TABLE          mep_attribute_table
239 #undef  TARGET_COMP_TYPE_ATTRIBUTES
240 #define TARGET_COMP_TYPE_ATTRIBUTES     mep_comp_type_attributes
241 #undef  TARGET_INSERT_ATTRIBUTES
242 #define TARGET_INSERT_ATTRIBUTES        mep_insert_attributes
243 #undef  TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
244 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P   mep_function_attribute_inlinable_p
245 #undef  TARGET_CAN_INLINE_P
246 #define TARGET_CAN_INLINE_P             mep_can_inline_p
247 #undef  TARGET_SECTION_TYPE_FLAGS
248 #define TARGET_SECTION_TYPE_FLAGS       mep_section_type_flags
249 #undef  TARGET_ASM_NAMED_SECTION
250 #define TARGET_ASM_NAMED_SECTION        mep_asm_named_section
251 #undef  TARGET_INIT_BUILTINS
252 #define TARGET_INIT_BUILTINS            mep_init_builtins
253 #undef  TARGET_EXPAND_BUILTIN
254 #define TARGET_EXPAND_BUILTIN           mep_expand_builtin
255 #undef  TARGET_SCHED_ADJUST_COST
256 #define TARGET_SCHED_ADJUST_COST        mep_adjust_cost
257 #undef  TARGET_SCHED_ISSUE_RATE
258 #define TARGET_SCHED_ISSUE_RATE         mep_issue_rate
259 #undef  TARGET_SCHED_REORDER
260 #define TARGET_SCHED_REORDER            mep_sched_reorder
261 #undef  TARGET_STRIP_NAME_ENCODING
262 #define TARGET_STRIP_NAME_ENCODING      mep_strip_name_encoding
263 #undef  TARGET_ASM_SELECT_SECTION
264 #define TARGET_ASM_SELECT_SECTION       mep_select_section
265 #undef  TARGET_ASM_UNIQUE_SECTION
266 #define TARGET_ASM_UNIQUE_SECTION       mep_unique_section
267 #undef  TARGET_ENCODE_SECTION_INFO
268 #define TARGET_ENCODE_SECTION_INFO      mep_encode_section_info
269 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
270 #define TARGET_FUNCTION_OK_FOR_SIBCALL  mep_function_ok_for_sibcall
271 #undef  TARGET_RTX_COSTS
272 #define TARGET_RTX_COSTS                mep_rtx_cost
273 #undef  TARGET_ADDRESS_COST
274 #define TARGET_ADDRESS_COST             mep_address_cost
275 #undef  TARGET_MACHINE_DEPENDENT_REORG
276 #define TARGET_MACHINE_DEPENDENT_REORG  mep_reorg
277 #undef  TARGET_SETUP_INCOMING_VARARGS
278 #define TARGET_SETUP_INCOMING_VARARGS   mep_setup_incoming_varargs
279 #undef  TARGET_PASS_BY_REFERENCE
280 #define TARGET_PASS_BY_REFERENCE        mep_pass_by_reference
281 #undef  TARGET_VECTOR_MODE_SUPPORTED_P
282 #define TARGET_VECTOR_MODE_SUPPORTED_P  mep_vector_mode_supported_p
283 #undef  TARGET_HANDLE_OPTION
284 #define TARGET_HANDLE_OPTION            mep_handle_option
285 #undef  TARGET_DEFAULT_TARGET_FLAGS
286 #define TARGET_DEFAULT_TARGET_FLAGS     TARGET_DEFAULT
287 #undef  TARGET_ALLOCATE_INITIAL_VALUE
288 #define TARGET_ALLOCATE_INITIAL_VALUE   mep_allocate_initial_value
289 #undef  TARGET_ASM_INIT_SECTIONS
290 #define TARGET_ASM_INIT_SECTIONS        mep_asm_init_sections
291 #undef  TARGET_RETURN_IN_MEMORY
292 #define TARGET_RETURN_IN_MEMORY         mep_return_in_memory
293 #undef  TARGET_NARROW_VOLATILE_BITFIELD
294 #define TARGET_NARROW_VOLATILE_BITFIELD mep_narrow_volatile_bitfield
295 #undef  TARGET_EXPAND_BUILTIN_SAVEREGS
296 #define TARGET_EXPAND_BUILTIN_SAVEREGS  mep_expand_builtin_saveregs
297 #undef  TARGET_BUILD_BUILTIN_VA_LIST
298 #define TARGET_BUILD_BUILTIN_VA_LIST    mep_build_builtin_va_list
299 #undef  TARGET_EXPAND_BUILTIN_VA_START
300 #define TARGET_EXPAND_BUILTIN_VA_START  mep_expand_va_start
301 #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
302 #define TARGET_GIMPLIFY_VA_ARG_EXPR     mep_gimplify_va_arg_expr
303 #undef TARGET_CAN_ELIMINATE
304 #define TARGET_CAN_ELIMINATE            mep_can_eliminate
305
306 struct gcc_target targetm = TARGET_INITIALIZER;
307 \f
308 #define WANT_GCC_DEFINITIONS
309 #include "mep-intrin.h"
310 #undef WANT_GCC_DEFINITIONS
311
312 \f
313 /* Command Line Option Support.  */
314
315 char mep_leaf_registers [FIRST_PSEUDO_REGISTER];
316
317 /* True if we can use cmov instructions to move values back and forth
318    between core and coprocessor registers.  */
319 bool mep_have_core_copro_moves_p;
320
321 /* True if we can use cmov instructions (or a work-alike) to move
322    values between coprocessor registers.  */
323 bool mep_have_copro_copro_moves_p;
324
325 /* A table of all coprocessor instructions that can act like
326    a coprocessor-to-coprocessor cmov.  */
327 static const int mep_cmov_insns[] = {
328   mep_cmov,
329   mep_cpmov,
330   mep_fmovs,
331   mep_caddi3,
332   mep_csubi3,
333   mep_candi3,
334   mep_cori3,
335   mep_cxori3,
336   mep_cand3,
337   mep_cor3
338 };
339
340 static int option_mtiny_specified = 0;
341
342 \f
343 static void
344 mep_set_leaf_registers (int enable)
345 {
346   int i;
347
348   if (mep_leaf_registers[0] != enable)
349     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
350       mep_leaf_registers[i] = enable;
351 }
352
353 void
354 mep_conditional_register_usage (char *fixed_regs, char *call_used_regs)
355 {
356   int i;
357
358   if (!TARGET_OPT_MULT && !TARGET_OPT_DIV)
359     {
360       fixed_regs[HI_REGNO] = 1;
361       fixed_regs[LO_REGNO] = 1;
362       call_used_regs[HI_REGNO] = 1;
363       call_used_regs[LO_REGNO] = 1;
364     }
365
366   for (i = FIRST_SHADOW_REGISTER; i <= LAST_SHADOW_REGISTER; i++)
367     global_regs[i] = 1;
368 }
369
370 void
371 mep_optimization_options (void)
372 {
373   /* The first scheduling pass often increases register pressure and tends
374      to result in more spill code.  Only run it when specifically asked.  */
375   flag_schedule_insns = 0;
376
377   /* Using $fp doesn't gain us much, even when debugging is important.  */
378   flag_omit_frame_pointer = 1;
379 }
380
381 void
382 mep_override_options (void)
383 {
384   if (flag_pic == 1)
385     warning (OPT_fpic, "-fpic is not supported");
386   if (flag_pic == 2)
387     warning (OPT_fPIC, "-fPIC is not supported");
388   if (TARGET_S && TARGET_M)
389     error ("only one of -ms and -mm may be given");
390   if (TARGET_S && TARGET_L)
391     error ("only one of -ms and -ml may be given");
392   if (TARGET_M && TARGET_L)
393     error ("only one of -mm and -ml may be given");
394   if (TARGET_S && option_mtiny_specified)
395     error ("only one of -ms and -mtiny= may be given");
396   if (TARGET_M && option_mtiny_specified)
397     error ("only one of -mm and -mtiny= may be given");
398   if (TARGET_OPT_CLIP && ! TARGET_OPT_MINMAX)
399     warning (0, "-mclip currently has no effect without -mminmax");
400
401   if (mep_const_section)
402     {
403       if (strcmp (mep_const_section, "tiny") != 0
404           && strcmp (mep_const_section, "near") != 0
405           && strcmp (mep_const_section, "far") != 0)
406         error ("-mc= must be -mc=tiny, -mc=near, or -mc=far");
407     }
408
409   if (TARGET_S)
410     mep_tiny_cutoff = 65536;
411   if (TARGET_M)
412     mep_tiny_cutoff = 0;
413   if (TARGET_L && ! option_mtiny_specified)
414     mep_tiny_cutoff = 0;
415
416   if (TARGET_64BIT_CR_REGS)
417     flag_split_wide_types = 0;
418
419   init_machine_status = mep_init_machine_status;
420   mep_init_intrinsics ();
421 }
422   
423 /* Pattern Support - constraints, predicates, expanders.  */
424
425 /* MEP has very few instructions that can refer to the span of
426    addresses used by symbols, so it's common to check for them.  */
427
428 static bool
429 symbol_p (rtx x)
430 {
431   int c = GET_CODE (x);
432
433   return (c == CONST_INT
434           || c == CONST
435           || c == SYMBOL_REF);
436 }
437
438 static bool
439 symbolref_p (rtx x)
440 {
441   int c;
442
443   if (GET_CODE (x) != MEM)
444     return false;
445
446   c = GET_CODE (XEXP (x, 0));
447   return (c == CONST_INT
448           || c == CONST
449           || c == SYMBOL_REF);
450 }
451
452 /* static const char *reg_class_names[] = REG_CLASS_NAMES; */
453
454 #define GEN_REG(R, STRICT)                              \
455   (GR_REGNO_P (R)                                       \
456    || (!STRICT                                          \
457        && ((R) == ARG_POINTER_REGNUM                    \
458            || (R) >= FIRST_PSEUDO_REGISTER)))
459
460 static char pattern[12], *patternp;
461 static GTY(()) rtx patternr[12];
462 #define RTX_IS(x) (strcmp (pattern, x) == 0)
463
464 static void
465 encode_pattern_1 (rtx x)
466 {
467   int i;
468
469   if (patternp == pattern + sizeof (pattern) - 2)
470     {
471       patternp[-1] = '?';
472       return;
473     }
474
475   patternr[patternp-pattern] = x;
476
477   switch (GET_CODE (x))
478     {
479     case REG:
480       *patternp++ = 'r';
481       break;
482     case MEM:
483       *patternp++ = 'm';
484     case CONST:
485       encode_pattern_1 (XEXP(x, 0));
486       break;
487     case PLUS:
488       *patternp++ = '+';
489       encode_pattern_1 (XEXP(x, 0));
490       encode_pattern_1 (XEXP(x, 1));
491       break;
492     case LO_SUM:
493       *patternp++ = 'L';
494       encode_pattern_1 (XEXP(x, 0));
495       encode_pattern_1 (XEXP(x, 1));
496       break;
497     case HIGH:
498       *patternp++ = 'H';
499       encode_pattern_1 (XEXP(x, 0));
500       break;
501     case SYMBOL_REF:
502       *patternp++ = 's';
503       break;
504     case LABEL_REF:
505       *patternp++ = 'l';
506       break;
507     case CONST_INT:
508     case CONST_DOUBLE:
509       *patternp++ = 'i';
510       break;
511     case UNSPEC:
512       *patternp++ = 'u';
513       *patternp++ = '0' + XCINT(x, 1, UNSPEC);
514       for (i=0; i<XVECLEN (x, 0); i++)
515         encode_pattern_1 (XVECEXP (x, 0, i));
516       break;
517     case USE:
518       *patternp++ = 'U';
519       break;
520     default:
521       *patternp++ = '?';
522 #if 0
523       fprintf (stderr, "can't encode pattern %s\n", GET_RTX_NAME(GET_CODE(x)));
524       debug_rtx (x);
525       gcc_unreachable ();
526 #endif
527       break;
528     }      
529 }
530
531 static void
532 encode_pattern (rtx x)
533 {
534   patternp = pattern;
535   encode_pattern_1 (x);
536   *patternp = 0;
537 }
538
539 int
540 mep_section_tag (rtx x)
541 {
542   const char *name;
543
544   while (1)
545     {
546       switch (GET_CODE (x))
547         {
548         case MEM:
549         case CONST:
550           x = XEXP (x, 0);
551           break;
552         case UNSPEC:
553           x = XVECEXP (x, 0, 0);
554           break;
555         case PLUS:
556           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
557             return 0;
558           x = XEXP (x, 0);
559           break;
560         default:
561           goto done;
562         }
563     }
564  done:
565   if (GET_CODE (x) != SYMBOL_REF)
566     return 0;
567   name = XSTR (x, 0);
568   if (name[0] == '@' && name[2] == '.')
569     {
570       if (name[1] == 'i' || name[1] == 'I')
571         {
572           if (name[1] == 'I')
573             return 'f'; /* near */
574           return 'n'; /* far */
575         }
576       return name[1];
577     }
578   return 0;
579 }
580
581 int
582 mep_regno_reg_class (int regno)
583 {
584   switch (regno)
585     {
586     case SP_REGNO:              return SP_REGS;
587     case TP_REGNO:              return TP_REGS;
588     case GP_REGNO:              return GP_REGS;
589     case 0:                     return R0_REGS;
590     case HI_REGNO:              return HI_REGS;
591     case LO_REGNO:              return LO_REGS;
592     case ARG_POINTER_REGNUM:    return GENERAL_REGS;
593     }
594
595   if (GR_REGNO_P (regno))
596     return regno < FIRST_GR_REGNO + 8 ? TPREL_REGS : GENERAL_REGS;
597   if (CONTROL_REGNO_P (regno))
598     return CONTROL_REGS;
599
600   if (CR_REGNO_P (regno))
601     {
602       int i, j;
603
604       /* Search for the register amongst user-defined subclasses of
605          the coprocessor registers.  */
606       for (i = USER0_REGS; i <= USER3_REGS; ++i)
607         {
608           if (! TEST_HARD_REG_BIT (reg_class_contents[i], regno))
609             continue;
610           for (j = 0; j < N_REG_CLASSES; ++j)
611             {
612               enum reg_class sub = reg_class_subclasses[i][j];
613
614               if (sub == LIM_REG_CLASSES)
615                 return i;
616               if (TEST_HARD_REG_BIT (reg_class_contents[sub], regno))
617                 break;
618             }
619         }
620
621       return LOADABLE_CR_REGNO_P (regno) ? LOADABLE_CR_REGS : CR_REGS;
622     }
623
624   if (CCR_REGNO_P (regno))
625     return CCR_REGS;
626
627   gcc_assert (regno >= FIRST_SHADOW_REGISTER && regno <= LAST_SHADOW_REGISTER);
628   return NO_REGS;
629 }
630
631 #if 0
632 int
633 mep_reg_class_from_constraint (int c, const char *str)
634 {
635   switch (c)
636     {
637     case 'a':
638       return SP_REGS;
639     case 'b':
640       return TP_REGS;
641     case 'c':
642       return CONTROL_REGS;
643     case 'd':
644       return HILO_REGS;
645     case 'e':
646       {
647         switch (str[1])
648           {
649           case 'm':
650             return LOADABLE_CR_REGS;
651           case 'x':
652             return mep_have_copro_copro_moves_p ? CR_REGS : NO_REGS;
653           case 'r':
654             return mep_have_core_copro_moves_p ? CR_REGS : NO_REGS;
655           default:
656             return NO_REGS;
657           }
658       }
659     case 'h':
660       return HI_REGS;
661     case 'j':
662       return RPC_REGS;
663     case 'l':
664       return LO_REGS;
665     case 't':
666       return TPREL_REGS;
667     case 'v':
668       return GP_REGS;
669     case 'x':
670       return CR_REGS;
671     case 'y':
672       return CCR_REGS;
673     case 'z':
674       return R0_REGS;
675
676     case 'A':
677     case 'B':
678     case 'C':
679     case 'D':
680       {
681         enum reg_class which = c - 'A' + USER0_REGS;
682         return (reg_class_size[which] > 0 ? which : NO_REGS);
683       }
684
685     default:
686       return NO_REGS;
687     }
688 }
689
690 bool
691 mep_const_ok_for_letter_p (HOST_WIDE_INT value, int c)
692 {
693   switch (c)
694     {
695       case 'I': return value >= -32768 && value <      32768;
696       case 'J': return value >=      0 && value <      65536;
697       case 'K': return value >=      0 && value < 0x01000000;
698       case 'L': return value >=    -32 && value <         32;
699       case 'M': return value >=      0 && value <         32;
700       case 'N': return value >=      0 && value <         16;
701       case 'O':
702         if (value & 0xffff)
703           return false;
704         return value >= -2147483647-1 && value <= 2147483647;
705     default:
706       gcc_unreachable ();
707     }
708 }
709
710 bool
711 mep_extra_constraint (rtx value, int c)
712 {
713   encode_pattern (value);
714
715   switch (c)
716     {
717     case 'R':
718       /* For near symbols, like what call uses.  */
719       if (GET_CODE (value) == REG)
720         return 0;
721       return mep_call_address_operand (value, GET_MODE (value));
722
723     case 'S':
724       /* For signed 8-bit immediates.  */
725       return (GET_CODE (value) == CONST_INT
726               && INTVAL (value) >= -128
727               && INTVAL (value) <= 127);
728
729     case 'T':
730       /* For tp/gp relative symbol values.  */
731       return (RTX_IS ("u3s") || RTX_IS ("u2s")
732               || RTX_IS ("+u3si") || RTX_IS ("+u2si"));
733
734     case 'U':
735       /* Non-absolute memories.  */
736       return GET_CODE (value) == MEM && ! CONSTANT_P (XEXP (value, 0));
737
738     case 'W':
739       /* %hi(sym) */
740       return RTX_IS ("Hs");
741
742     case 'Y':
743       /* Register indirect.  */
744       return RTX_IS ("mr");
745
746     case 'Z':
747       return mep_section_tag (value) == 'c' && RTX_IS ("ms");
748     }
749
750   return false;
751 }
752 #endif
753
754 #undef PASS
755 #undef FAIL
756
757 static bool
758 const_in_range (rtx x, int minv, int maxv)
759 {
760   return (GET_CODE (x) == CONST_INT
761           && INTVAL (x) >= minv
762           && INTVAL (x) <= maxv);
763 }
764
765 /* Given three integer registers DEST, SRC1 and SRC2, return an rtx X
766    such that "mulr DEST,X" will calculate DEST = SRC1 * SRC2.  If a move
767    is needed, emit it before INSN if INSN is nonnull, otherwise emit it
768    at the end of the insn stream.  */
769
770 rtx
771 mep_mulr_source (rtx insn, rtx dest, rtx src1, rtx src2)
772 {
773   if (rtx_equal_p (dest, src1))
774     return src2;
775   else if (rtx_equal_p (dest, src2))
776     return src1;
777   else
778     {
779       if (insn == 0)
780         emit_insn (gen_movsi (copy_rtx (dest), src1));
781       else
782         emit_insn_before (gen_movsi (copy_rtx (dest), src1), insn);
783       return src2;
784     }
785 }
786
787 /* Replace INSN's pattern with PATTERN, a multiplication PARALLEL.
788    Change the last element of PATTERN from (clobber (scratch:SI))
789    to (clobber (reg:SI HI_REGNO)).  */
790
791 static void
792 mep_rewrite_mult (rtx insn, rtx pattern)
793 {
794   rtx hi_clobber;
795
796   hi_clobber = XVECEXP (pattern, 0, XVECLEN (pattern, 0) - 1);
797   XEXP (hi_clobber, 0) = gen_rtx_REG (SImode, HI_REGNO);
798   PATTERN (insn) = pattern;
799   INSN_CODE (insn) = -1;
800 }
801
802 /* Subroutine of mep_reuse_lo_p.  Rewrite instruction INSN so that it
803    calculates SRC1 * SRC2 and stores the result in $lo.  Also make it
804    store the result in DEST if nonnull.  */
805
806 static void
807 mep_rewrite_mulsi3 (rtx insn, rtx dest, rtx src1, rtx src2)
808 {
809   rtx lo, pattern;
810
811   lo = gen_rtx_REG (SImode, LO_REGNO);
812   if (dest)
813     pattern = gen_mulsi3r (lo, dest, copy_rtx (dest),
814                            mep_mulr_source (insn, dest, src1, src2));
815   else
816     pattern = gen_mulsi3_lo (lo, src1, src2);
817   mep_rewrite_mult (insn, pattern);
818 }
819
820 /* Like mep_rewrite_mulsi3, but calculate SRC1 * SRC2 + SRC3.  First copy
821    SRC3 into $lo, then use either madd or maddr.  The move into $lo will
822    be deleted by a peephole2 if SRC3 is already in $lo.  */
823
824 static void
825 mep_rewrite_maddsi3 (rtx insn, rtx dest, rtx src1, rtx src2, rtx src3)
826 {
827   rtx lo, pattern;
828
829   lo = gen_rtx_REG (SImode, LO_REGNO);
830   emit_insn_before (gen_movsi (copy_rtx (lo), src3), insn);
831   if (dest)
832     pattern = gen_maddsi3r (lo, dest, copy_rtx (dest),
833                             mep_mulr_source (insn, dest, src1, src2),
834                             copy_rtx (lo));
835   else
836     pattern = gen_maddsi3_lo (lo, src1, src2, copy_rtx (lo));
837   mep_rewrite_mult (insn, pattern);
838 }
839
840 /* Return true if $lo has the same value as integer register GPR when
841    instruction INSN is reached.  If necessary, rewrite the instruction
842    that sets $lo so that it uses a proper SET, not a CLOBBER.  LO is an
843    rtx for (reg:SI LO_REGNO).
844
845    This function is intended to be used by the peephole2 pass.  Since
846    that pass goes from the end of a basic block to the beginning, and
847    propagates liveness information on the way, there is no need to
848    update register notes here.
849
850    If GPR_DEAD_P is true on entry, and this function returns true,
851    then the caller will replace _every_ use of GPR in and after INSN
852    with LO.  This means that if the instruction that sets $lo is a
853    mulr- or maddr-type instruction, we can rewrite it to use mul or
854    madd instead.  In combination with the copy progagation pass,
855    this allows us to replace sequences like:
856
857         mov GPR,R1
858         mulr GPR,R2
859
860    with:
861
862         mul R1,R2
863
864    if GPR is no longer used.  */
865
866 static bool
867 mep_reuse_lo_p_1 (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
868 {
869   do
870     {
871       insn = PREV_INSN (insn);
872       if (INSN_P (insn))
873         switch (recog_memoized (insn))
874           {
875           case CODE_FOR_mulsi3_1:
876             extract_insn (insn);
877             if (rtx_equal_p (recog_data.operand[0], gpr))
878               {
879                 mep_rewrite_mulsi3 (insn,
880                                     gpr_dead_p ? NULL : recog_data.operand[0],
881                                     recog_data.operand[1],
882                                     recog_data.operand[2]);
883                 return true;
884               }
885             return false;
886
887           case CODE_FOR_maddsi3:
888             extract_insn (insn);
889             if (rtx_equal_p (recog_data.operand[0], gpr))
890               {
891                 mep_rewrite_maddsi3 (insn,
892                                      gpr_dead_p ? NULL : recog_data.operand[0],
893                                      recog_data.operand[1],
894                                      recog_data.operand[2],
895                                      recog_data.operand[3]);
896                 return true;
897               }
898             return false;
899
900           case CODE_FOR_mulsi3r:
901           case CODE_FOR_maddsi3r:
902             extract_insn (insn);
903             return rtx_equal_p (recog_data.operand[1], gpr);
904
905           default:
906             if (reg_set_p (lo, insn)
907                 || reg_set_p (gpr, insn)
908                 || volatile_insn_p (PATTERN (insn)))
909               return false;
910
911             if (gpr_dead_p && reg_referenced_p (gpr, PATTERN (insn)))
912               gpr_dead_p = false;
913             break;
914           }
915     }
916   while (!NOTE_INSN_BASIC_BLOCK_P (insn));
917   return false;
918 }
919
920 /* A wrapper around mep_reuse_lo_p_1 that preserves recog_data.  */
921
922 bool
923 mep_reuse_lo_p (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p)
924 {
925   bool result = mep_reuse_lo_p_1 (lo, gpr, insn, gpr_dead_p);
926   extract_insn (insn);
927   return result;
928 }
929
930 /* Return true if SET can be turned into a post-modify load or store
931    that adds OFFSET to GPR.  In other words, return true if SET can be
932    changed into:
933
934        (parallel [SET (set GPR (plus:SI GPR OFFSET))]).
935
936    It's OK to change SET to an equivalent operation in order to
937    make it match.  */
938
939 static bool
940 mep_use_post_modify_for_set_p (rtx set, rtx gpr, rtx offset)
941 {
942   rtx *reg, *mem;
943   unsigned int reg_bytes, mem_bytes;
944   enum machine_mode reg_mode, mem_mode;
945
946   /* Only simple SETs can be converted.  */
947   if (GET_CODE (set) != SET)
948     return false;
949
950   /* Point REG to what we hope will be the register side of the set and
951      MEM to what we hope will be the memory side.  */
952   if (GET_CODE (SET_DEST (set)) == MEM)
953     {
954       mem = &SET_DEST (set);
955       reg = &SET_SRC (set);
956     }
957   else
958     {
959       reg = &SET_DEST (set);
960       mem = &SET_SRC (set);
961       if (GET_CODE (*mem) == SIGN_EXTEND)
962         mem = &XEXP (*mem, 0);
963     }
964
965   /* Check that *REG is a suitable coprocessor register.  */
966   if (GET_CODE (*reg) != REG || !LOADABLE_CR_REGNO_P (REGNO (*reg)))
967     return false;
968
969   /* Check that *MEM is a suitable memory reference.  */
970   if (GET_CODE (*mem) != MEM || !rtx_equal_p (XEXP (*mem, 0), gpr))
971     return false;
972
973   /* Get the number of bytes in each operand.  */
974   mem_bytes = GET_MODE_SIZE (GET_MODE (*mem));
975   reg_bytes = GET_MODE_SIZE (GET_MODE (*reg));
976
977   /* Check that OFFSET is suitably aligned.  */
978   if (INTVAL (offset) & (mem_bytes - 1))
979     return false;
980
981   /* Convert *MEM to a normal integer mode.  */
982   mem_mode = mode_for_size (mem_bytes * BITS_PER_UNIT, MODE_INT, 0);
983   *mem = change_address (*mem, mem_mode, NULL);
984
985   /* Adjust *REG as well.  */
986   *reg = shallow_copy_rtx (*reg);
987   if (reg == &SET_DEST (set) && reg_bytes < UNITS_PER_WORD)
988     {
989       /* SET is a subword load.  Convert it to an explicit extension.  */
990       PUT_MODE (*reg, SImode);
991       *mem = gen_rtx_SIGN_EXTEND (SImode, *mem);
992     }
993   else
994     {
995       reg_mode = mode_for_size (reg_bytes * BITS_PER_UNIT, MODE_INT, 0);
996       PUT_MODE (*reg, reg_mode);
997     }
998   return true;
999 }
1000
1001 /* Return the effect of frame-related instruction INSN.  */
1002
1003 static rtx
1004 mep_frame_expr (rtx insn)
1005 {
1006   rtx note, expr;
1007
1008   note = find_reg_note (insn, REG_FRAME_RELATED_EXPR, 0);
1009   expr = (note != 0 ? XEXP (note, 0) : copy_rtx (PATTERN (insn)));
1010   RTX_FRAME_RELATED_P (expr) = 1;
1011   return expr;
1012 }
1013
1014 /* Merge instructions INSN1 and INSN2 using a PARALLEL.  Store the
1015    new pattern in INSN1; INSN2 will be deleted by the caller.  */
1016
1017 static void
1018 mep_make_parallel (rtx insn1, rtx insn2)
1019 {
1020   rtx expr;
1021
1022   if (RTX_FRAME_RELATED_P (insn2))
1023     {
1024       expr = mep_frame_expr (insn2);
1025       if (RTX_FRAME_RELATED_P (insn1))
1026         expr = gen_rtx_SEQUENCE (VOIDmode,
1027                                  gen_rtvec (2, mep_frame_expr (insn1), expr));
1028       set_unique_reg_note (insn1, REG_FRAME_RELATED_EXPR, expr);
1029       RTX_FRAME_RELATED_P (insn1) = 1;
1030     }
1031
1032   PATTERN (insn1) = gen_rtx_PARALLEL (VOIDmode,
1033                                       gen_rtvec (2, PATTERN (insn1),
1034                                                  PATTERN (insn2)));
1035   INSN_CODE (insn1) = -1;
1036 }
1037
1038 /* SET_INSN is an instruction that adds OFFSET to REG.  Go back through
1039    the basic block to see if any previous load or store instruction can
1040    be persuaded to do SET_INSN as a side-effect.  Return true if so.  */
1041
1042 static bool
1043 mep_use_post_modify_p_1 (rtx set_insn, rtx reg, rtx offset)
1044 {
1045   rtx insn;
1046
1047   insn = set_insn;
1048   do
1049     {
1050       insn = PREV_INSN (insn);
1051       if (INSN_P (insn))
1052         {
1053           if (mep_use_post_modify_for_set_p (PATTERN (insn), reg, offset))
1054             {
1055               mep_make_parallel (insn, set_insn);
1056               return true;
1057             }
1058
1059           if (reg_set_p (reg, insn)
1060               || reg_referenced_p (reg, PATTERN (insn))
1061               || volatile_insn_p (PATTERN (insn)))
1062             return false;
1063         }
1064     }
1065   while (!NOTE_INSN_BASIC_BLOCK_P (insn));
1066   return false;
1067 }
1068
1069 /* A wrapper around mep_use_post_modify_p_1 that preserves recog_data.  */
1070
1071 bool
1072 mep_use_post_modify_p (rtx insn, rtx reg, rtx offset)
1073 {
1074   bool result = mep_use_post_modify_p_1 (insn, reg, offset);
1075   extract_insn (insn);
1076   return result;
1077 }
1078
1079 bool
1080 mep_allow_clip (rtx ux, rtx lx, int s)
1081 {
1082   HOST_WIDE_INT u = INTVAL (ux);
1083   HOST_WIDE_INT l = INTVAL (lx);
1084   int i;
1085
1086   if (!TARGET_OPT_CLIP)
1087     return false;
1088
1089   if (s)
1090     {
1091       for (i = 0; i < 30; i ++)
1092         if ((u == ((HOST_WIDE_INT) 1 << i) - 1)
1093             && (l == - ((HOST_WIDE_INT) 1 << i)))
1094           return true;
1095     }
1096   else
1097     {
1098       if (l != 0)
1099         return false;
1100
1101       for (i = 0; i < 30; i ++)
1102         if ((u == ((HOST_WIDE_INT) 1 << i) - 1))
1103           return true;
1104     }
1105   return false;
1106 }
1107
1108 bool
1109 mep_bit_position_p (rtx x, bool looking_for)
1110 {
1111   if (GET_CODE (x) != CONST_INT)
1112     return false;
1113   switch ((int) INTVAL(x) & 0xff)
1114     {
1115     case 0x01: case 0x02: case 0x04: case 0x08:
1116     case 0x10: case 0x20: case 0x40: case 0x80:
1117       return looking_for;
1118     case 0xfe: case 0xfd: case 0xfb: case 0xf7:
1119     case 0xef: case 0xdf: case 0xbf: case 0x7f:
1120       return !looking_for;
1121     }
1122   return false;
1123 }
1124
1125 static bool
1126 move_needs_splitting (rtx dest, rtx src,
1127                       enum machine_mode mode ATTRIBUTE_UNUSED)
1128 {
1129   int s = mep_section_tag (src);
1130
1131   while (1)
1132     {
1133       if (GET_CODE (src) == CONST
1134           || GET_CODE (src) == MEM)
1135         src = XEXP (src, 0);
1136       else if (GET_CODE (src) == SYMBOL_REF
1137                || GET_CODE (src) == LABEL_REF
1138                || GET_CODE (src) == PLUS)
1139         break;
1140       else
1141         return false;
1142     }
1143   if (s == 'f'
1144       || (GET_CODE (src) == PLUS
1145           && GET_CODE (XEXP (src, 1)) == CONST_INT
1146           && (INTVAL (XEXP (src, 1)) < -65536
1147               || INTVAL (XEXP (src, 1)) > 0xffffff))
1148       || (GET_CODE (dest) == REG
1149           && REGNO (dest) > 7 && REGNO (dest) < FIRST_PSEUDO_REGISTER))
1150     return true;
1151   return false;
1152 }
1153
1154 bool
1155 mep_split_mov (rtx *operands, int symbolic)
1156 {
1157   if (symbolic)
1158     {
1159       if (move_needs_splitting (operands[0], operands[1], SImode))
1160         return true;
1161       return false;
1162     }
1163
1164   if (GET_CODE (operands[1]) != CONST_INT)
1165     return false;
1166
1167   if (constraint_satisfied_p (operands[1], CONSTRAINT_I)
1168       || constraint_satisfied_p (operands[1], CONSTRAINT_J)
1169       || constraint_satisfied_p (operands[1], CONSTRAINT_O))
1170     return false;
1171
1172   if (((!reload_completed && !reload_in_progress)
1173        || (REG_P (operands[0]) && REGNO (operands[0]) < 8))
1174       && constraint_satisfied_p (operands[1], CONSTRAINT_K))
1175     return false;
1176
1177   return true;
1178 }
1179
1180 /* Irritatingly, the "jsrv" insn *toggles* PSW.OM rather than set
1181    it to one specific value.  So the insn chosen depends on whether
1182    the source and destination modes match.  */
1183
1184 bool
1185 mep_vliw_mode_match (rtx tgt)
1186 {
1187   bool src_vliw = mep_vliw_function_p (cfun->decl);
1188   bool tgt_vliw = INTVAL (tgt);
1189
1190   return src_vliw == tgt_vliw;
1191 }
1192
1193 /* Like the above, but also test for near/far mismatches.  */
1194
1195 bool
1196 mep_vliw_jmp_match (rtx tgt)
1197 {
1198   bool src_vliw = mep_vliw_function_p (cfun->decl);
1199   bool tgt_vliw = INTVAL (tgt);
1200
1201   if (mep_section_tag (DECL_RTL (cfun->decl)) == 'f')
1202     return false;
1203
1204   return src_vliw == tgt_vliw;
1205 }
1206
1207 bool
1208 mep_multi_slot (rtx x)
1209 {
1210   return get_attr_slot (x) == SLOT_MULTI;
1211 }
1212
1213
1214 /* Be careful not to use macros that need to be compiled one way for
1215    strict, and another way for not-strict, like REG_OK_FOR_BASE_P.  */
1216
1217 bool
1218 mep_legitimate_address (enum machine_mode mode, rtx x, int strict)
1219 {
1220   int the_tag;
1221
1222 #define DEBUG_LEGIT 0
1223 #if DEBUG_LEGIT
1224   fprintf (stderr, "legit: mode %s strict %d ", mode_name[mode], strict);
1225   debug_rtx (x);
1226 #endif
1227
1228   if (GET_CODE (x) == LO_SUM
1229       && GET_CODE (XEXP (x, 0)) == REG
1230       && GEN_REG (REGNO (XEXP (x, 0)), strict)
1231       && CONSTANT_P (XEXP (x, 1)))
1232     {
1233       if (GET_MODE_SIZE (mode) > 4)
1234         {
1235           /* We will end up splitting this, and lo_sums are not
1236              offsettable for us.  */
1237 #if DEBUG_LEGIT
1238           fprintf(stderr, " - nope, %%lo(sym)[reg] not splittable\n");
1239 #endif
1240           return false;
1241         }
1242 #if DEBUG_LEGIT
1243       fprintf (stderr, " - yup, %%lo(sym)[reg]\n");
1244 #endif
1245       return true;
1246     }
1247
1248   if (GET_CODE (x) == REG
1249       && GEN_REG (REGNO (x), strict))
1250     {
1251 #if DEBUG_LEGIT
1252       fprintf (stderr, " - yup, [reg]\n");
1253 #endif
1254       return true;
1255     }
1256
1257   if (GET_CODE (x) == PLUS
1258       && GET_CODE (XEXP (x, 0)) == REG
1259       && GEN_REG (REGNO (XEXP (x, 0)), strict)
1260       && const_in_range (XEXP (x, 1), -32768, 32767))
1261     {
1262 #if DEBUG_LEGIT
1263       fprintf (stderr, " - yup, [reg+const]\n");
1264 #endif
1265       return true;
1266     }
1267
1268   if (GET_CODE (x) == PLUS
1269       && GET_CODE (XEXP (x, 0)) == REG
1270       && GEN_REG (REGNO (XEXP (x, 0)), strict)
1271       && GET_CODE (XEXP (x, 1)) == CONST
1272       && (GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
1273           || (GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
1274               && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == UNSPEC
1275               && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)))
1276     {
1277 #if DEBUG_LEGIT
1278       fprintf (stderr, " - yup, [reg+unspec]\n");
1279 #endif
1280       return true;
1281     }
1282
1283   the_tag = mep_section_tag (x);
1284
1285   if (the_tag == 'f')
1286     {
1287 #if DEBUG_LEGIT
1288       fprintf (stderr, " - nope, [far]\n");
1289 #endif
1290       return false;
1291     }
1292
1293   if (mode == VOIDmode
1294       && GET_CODE (x) == SYMBOL_REF)
1295     {
1296 #if DEBUG_LEGIT
1297       fprintf (stderr, " - yup, call [symbol]\n");
1298 #endif
1299       return true;
1300     }
1301
1302   if ((mode == SImode || mode == SFmode)
1303       && CONSTANT_P (x)
1304       && LEGITIMATE_CONSTANT_P (x)
1305       && the_tag != 't' && the_tag != 'b')
1306     {
1307       if (GET_CODE (x) != CONST_INT
1308           || (INTVAL (x) <= 0xfffff
1309               && INTVAL (x) >= 0
1310               && (INTVAL (x) % 4) == 0))
1311         {
1312 #if DEBUG_LEGIT
1313           fprintf (stderr, " - yup, [const]\n");
1314 #endif
1315           return true;
1316         }
1317     }
1318
1319 #if DEBUG_LEGIT
1320   fprintf (stderr, " - nope.\n");
1321 #endif
1322   return false;
1323 }
1324
1325 int
1326 mep_legitimize_reload_address (rtx *x, enum machine_mode mode, int opnum,
1327                                enum reload_type type,
1328                                int ind_levels ATTRIBUTE_UNUSED)
1329 {
1330   if (GET_CODE (*x) == PLUS
1331       && GET_CODE (XEXP (*x, 0)) == MEM
1332       && GET_CODE (XEXP (*x, 1)) == REG)
1333     {
1334       /* GCC will by default copy the MEM into a REG, which results in
1335          an invalid address.  For us, the best thing to do is move the
1336          whole expression to a REG.  */
1337       push_reload (*x, NULL_RTX, x, NULL,
1338                    GENERAL_REGS, mode, VOIDmode,
1339                    0, 0, opnum, type);
1340       return 1;
1341     }
1342
1343   if (GET_CODE (*x) == PLUS
1344       && GET_CODE (XEXP (*x, 0)) == SYMBOL_REF
1345       && GET_CODE (XEXP (*x, 1)) == CONST_INT)
1346     {
1347       char e = mep_section_tag (XEXP (*x, 0));
1348
1349       if (e != 't' && e != 'b')
1350         {
1351           /* GCC thinks that (sym+const) is a valid address.  Well,
1352              sometimes it is, this time it isn't.  The best thing to
1353              do is reload the symbol to a register, since reg+int
1354              tends to work, and we can't just add the symbol and
1355              constant anyway.  */
1356           push_reload (XEXP (*x, 0), NULL_RTX, &(XEXP(*x, 0)), NULL,
1357                        GENERAL_REGS, mode, VOIDmode,
1358                        0, 0, opnum, type);
1359           return 1;
1360         }
1361     }
1362   return 0;
1363 }
1364
1365 int
1366 mep_core_address_length (rtx insn, int opn)
1367 {
1368   rtx set = single_set (insn);
1369   rtx mem = XEXP (set, opn);
1370   rtx other = XEXP (set, 1-opn);
1371   rtx addr = XEXP (mem, 0);
1372
1373   if (register_operand (addr, Pmode))
1374     return 2;
1375   if (GET_CODE (addr) == PLUS)
1376     {
1377       rtx addend = XEXP (addr, 1);
1378
1379       gcc_assert (REG_P (XEXP (addr, 0)));
1380
1381       switch (REGNO (XEXP (addr, 0)))
1382         {
1383         case STACK_POINTER_REGNUM:
1384           if (GET_MODE_SIZE (GET_MODE (mem)) == 4
1385               && mep_imm7a4_operand (addend, VOIDmode))
1386             return 2;
1387           break;
1388
1389         case 13: /* TP */
1390           gcc_assert (REG_P (other));
1391
1392           if (REGNO (other) >= 8)
1393             break;
1394
1395           if (GET_CODE (addend) == CONST
1396               && GET_CODE (XEXP (addend, 0)) == UNSPEC
1397               && XINT (XEXP (addend, 0), 1) == UNS_TPREL)
1398             return 2;
1399
1400           if (GET_CODE (addend) == CONST_INT
1401               && INTVAL (addend) >= 0
1402               && INTVAL (addend) <= 127
1403               && INTVAL (addend) % GET_MODE_SIZE (GET_MODE (mem)) == 0)
1404             return 2;
1405           break;
1406         }
1407     }
1408
1409   return 4;
1410 }
1411
1412 int
1413 mep_cop_address_length (rtx insn, int opn)
1414 {
1415   rtx set = single_set (insn);
1416   rtx mem = XEXP (set, opn);
1417   rtx addr = XEXP (mem, 0);
1418
1419   if (GET_CODE (mem) != MEM)
1420     return 2;
1421   if (register_operand (addr, Pmode))
1422     return 2;
1423   if (GET_CODE (addr) == POST_INC)
1424     return 2;
1425
1426   return 4;
1427 }
1428
1429 #define DEBUG_EXPAND_MOV 0
1430 bool
1431 mep_expand_mov (rtx *operands, enum machine_mode mode)
1432 {
1433   int i, t;
1434   int tag[2];
1435   rtx tpsym, tpoffs;
1436   int post_reload = 0;
1437
1438   tag[0] = mep_section_tag (operands[0]);
1439   tag[1] = mep_section_tag (operands[1]);
1440
1441   if (!reload_in_progress
1442       && !reload_completed
1443       && GET_CODE (operands[0]) != REG
1444       && GET_CODE (operands[0]) != SUBREG
1445       && GET_CODE (operands[1]) != REG
1446       && GET_CODE (operands[1]) != SUBREG)
1447     operands[1] = copy_to_mode_reg (mode, operands[1]);
1448   
1449 #if DEBUG_EXPAND_MOV
1450   fprintf(stderr, "expand move %s %d\n", mode_name[mode],
1451           reload_in_progress || reload_completed);
1452   debug_rtx (operands[0]);
1453   debug_rtx (operands[1]);
1454 #endif
1455
1456   if (mode == DImode || mode == DFmode)
1457     return false;
1458
1459   if (reload_in_progress || reload_completed)
1460     {
1461       rtx r;
1462
1463       if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == TP_REGNO)
1464         cfun->machine->reload_changes_tp = true;
1465
1466       if (tag[0] == 't' || tag[1] == 't')
1467         {
1468           r = has_hard_reg_initial_val (Pmode, GP_REGNO);
1469           if (!r || GET_CODE (r) != REG || REGNO (r) != GP_REGNO)
1470             post_reload = 1;
1471         }
1472       if (tag[0] == 'b' || tag[1] == 'b')
1473         {
1474           r = has_hard_reg_initial_val (Pmode, TP_REGNO);
1475           if (!r || GET_CODE (r) != REG || REGNO (r) != TP_REGNO)
1476             post_reload = 1;
1477         }
1478       if (cfun->machine->reload_changes_tp == true)
1479         post_reload = 1;
1480     }
1481
1482   if (!post_reload)
1483     {
1484       rtx n;
1485       if (symbol_p (operands[1]))
1486         {
1487           t = mep_section_tag (operands[1]);
1488           if (t == 'b' || t == 't')
1489             {
1490
1491               if (GET_CODE (operands[1]) == SYMBOL_REF)
1492                 {
1493                   tpsym = operands[1];
1494                   n = gen_rtx_UNSPEC (mode,
1495                                       gen_rtvec (1, operands[1]),
1496                                       t == 'b' ? UNS_TPREL : UNS_GPREL);
1497                   n = gen_rtx_CONST (mode, n);
1498                 }
1499               else if (GET_CODE (operands[1]) == CONST
1500                        && GET_CODE (XEXP (operands[1], 0)) == PLUS
1501                        && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
1502                        && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
1503                 {
1504                   tpsym = XEXP (XEXP (operands[1], 0), 0);
1505                   tpoffs = XEXP (XEXP (operands[1], 0), 1);
1506                   n = gen_rtx_UNSPEC (mode,
1507                                       gen_rtvec (1, tpsym),
1508                                       t == 'b' ? UNS_TPREL : UNS_GPREL);
1509                   n = gen_rtx_PLUS (mode, n, tpoffs);
1510                   n = gen_rtx_CONST (mode, n);
1511                 }
1512               else if (GET_CODE (operands[1]) == CONST
1513                        && GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
1514                 return false;
1515               else
1516                 {
1517                   error ("unusual TP-relative address");
1518                   return false;
1519                 }
1520
1521               n = gen_rtx_PLUS (mode, (t == 'b' ? mep_tp_rtx ()
1522                                        : mep_gp_rtx ()), n);
1523               n = emit_insn (gen_rtx_SET (mode, operands[0], n));
1524 #if DEBUG_EXPAND_MOV
1525               fprintf(stderr, "mep_expand_mov emitting ");
1526               debug_rtx(n);
1527 #endif
1528               return true;
1529             }
1530         }
1531
1532       for (i=0; i < 2; i++)
1533         {
1534           t = mep_section_tag (operands[i]);
1535           if (GET_CODE (operands[i]) == MEM && (t == 'b' || t == 't'))
1536             {
1537               rtx sym, n, r;
1538               int u;
1539
1540               sym = XEXP (operands[i], 0);
1541               if (GET_CODE (sym) == CONST
1542                   && GET_CODE (XEXP (sym, 0)) == UNSPEC)
1543                 sym = XVECEXP (XEXP (sym, 0), 0, 0);
1544
1545               if (t == 'b')
1546                 {
1547                   r = mep_tp_rtx ();
1548                   u = UNS_TPREL;
1549                 }
1550               else
1551                 {
1552                   r = mep_gp_rtx ();
1553                   u = UNS_GPREL;
1554                 }
1555
1556               n = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), u);
1557               n = gen_rtx_CONST (Pmode, n);
1558               n = gen_rtx_PLUS (Pmode, r, n);
1559               operands[i] = replace_equiv_address (operands[i], n);
1560             }
1561         }
1562     }
1563
1564   if ((GET_CODE (operands[1]) != REG
1565        && MEP_CONTROL_REG (operands[0]))
1566       || (GET_CODE (operands[0]) != REG
1567           && MEP_CONTROL_REG (operands[1])))
1568     {
1569       rtx temp;
1570 #if DEBUG_EXPAND_MOV
1571       fprintf (stderr, "cr-mem, forcing op1 to reg\n");
1572 #endif
1573       temp = gen_reg_rtx (mode);
1574       emit_move_insn (temp, operands[1]);
1575       operands[1] = temp;
1576     }
1577
1578   if (symbolref_p (operands[0])
1579       && (mep_section_tag (XEXP (operands[0], 0)) == 'f'
1580           || (GET_MODE_SIZE (mode) != 4)))
1581     {
1582       rtx temp;
1583
1584       gcc_assert (!reload_in_progress && !reload_completed);
1585
1586       temp = force_reg (Pmode, XEXP (operands[0], 0));
1587       operands[0] = replace_equiv_address (operands[0], temp);
1588       emit_move_insn (operands[0], operands[1]);
1589       return true;
1590     }
1591
1592   if (!post_reload && (tag[1] == 't' || tag[1] == 'b'))
1593     tag[1] = 0;
1594
1595   if (symbol_p (operands[1])
1596       && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1597     {
1598       emit_insn (gen_movsi_topsym_s (operands[0], operands[1]));
1599       emit_insn (gen_movsi_botsym_s (operands[0], operands[0], operands[1]));
1600       return true;
1601     }
1602
1603   if (symbolref_p (operands[1])
1604       && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b'))
1605     {
1606       rtx temp;
1607
1608       if (reload_in_progress || reload_completed)
1609         temp = operands[0];
1610       else
1611         temp = gen_reg_rtx (Pmode);
1612
1613       emit_insn (gen_movsi_topsym_s (temp, operands[1]));
1614       emit_insn (gen_movsi_botsym_s (temp, temp, operands[1]));
1615       emit_move_insn (operands[0], replace_equiv_address (operands[1], temp));
1616       return true;
1617     }
1618
1619   return false;
1620 }
1621
1622 /* Cases where the pattern can't be made to use at all.  */
1623
1624 bool
1625 mep_mov_ok (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1626 {
1627   int i;
1628
1629 #define DEBUG_MOV_OK 0
1630 #if DEBUG_MOV_OK
1631   fprintf (stderr, "mep_mov_ok %s %c=%c\n", mode_name[mode], mep_section_tag (operands[0]),
1632            mep_section_tag (operands[1]));
1633   debug_rtx (operands[0]);
1634   debug_rtx (operands[1]);
1635 #endif
1636
1637   /* We want the movh patterns to get these.  */
1638   if (GET_CODE (operands[1]) == HIGH)
1639     return false;
1640
1641   /* We can't store a register to a far variable without using a
1642      scratch register to hold the address.  Using far variables should
1643      be split by mep_emit_mov anyway.  */
1644   if (mep_section_tag (operands[0]) == 'f'
1645       || mep_section_tag (operands[1]) == 'f')
1646     {
1647 #if DEBUG_MOV_OK
1648       fprintf (stderr, " - no, f\n");
1649 #endif
1650       return false;
1651     }
1652   i = mep_section_tag (operands[1]);
1653   if ((i == 'b' || i == 't') && !reload_completed && !reload_in_progress)
1654     /* These are supposed to be generated with adds of the appropriate
1655        register.  During and after reload, however, we allow them to
1656        be accessed as normal symbols because adding a dependency on
1657        the base register now might cause problems.  */
1658     {
1659 #if DEBUG_MOV_OK
1660       fprintf (stderr, " - no, bt\n");
1661 #endif
1662       return false;
1663     }
1664
1665   /* The only moves we can allow involve at least one general
1666      register, so require it.  */
1667   for (i = 0; i < 2; i ++)
1668     {
1669       /* Allow subregs too, before reload.  */
1670       rtx x = operands[i];
1671
1672       if (GET_CODE (x) == SUBREG)
1673         x = XEXP (x, 0);
1674       if (GET_CODE (x) == REG
1675           && ! MEP_CONTROL_REG (x))
1676         {
1677 #if DEBUG_MOV_OK
1678           fprintf (stderr, " - ok\n");
1679 #endif
1680           return true;
1681         }
1682     }
1683 #if DEBUG_MOV_OK
1684   fprintf (stderr, " - no, no gen reg\n");
1685 #endif
1686   return false;
1687 }
1688
1689 #define DEBUG_SPLIT_WIDE_MOVE 0
1690 void
1691 mep_split_wide_move (rtx *operands, enum machine_mode mode)
1692 {
1693   int i;
1694
1695 #if DEBUG_SPLIT_WIDE_MOVE
1696   fprintf (stderr, "\n\033[34mmep_split_wide_move\033[0m mode %s\n", mode_name[mode]);
1697   debug_rtx (operands[0]);
1698   debug_rtx (operands[1]);
1699 #endif
1700
1701   for (i = 0; i <= 1; i++)
1702     {
1703       rtx op = operands[i], hi, lo;
1704
1705       switch (GET_CODE (op))
1706         {
1707         case REG:
1708           {
1709             unsigned int regno = REGNO (op);
1710
1711             if (TARGET_64BIT_CR_REGS && CR_REGNO_P (regno))
1712               {
1713                 rtx i32;
1714
1715                 lo = gen_rtx_REG (SImode, regno);
1716                 i32 = GEN_INT (32);
1717                 hi = gen_rtx_ZERO_EXTRACT (SImode,
1718                                            gen_rtx_REG (DImode, regno),
1719                                            i32, i32);
1720               }
1721             else
1722               {
1723                 hi = gen_rtx_REG (SImode, regno + TARGET_LITTLE_ENDIAN);
1724                 lo = gen_rtx_REG (SImode, regno + TARGET_BIG_ENDIAN);
1725               }
1726           }
1727           break;
1728
1729         case CONST_INT:
1730         case CONST_DOUBLE:
1731         case MEM:
1732           hi = operand_subword (op, TARGET_LITTLE_ENDIAN, 0, mode);
1733           lo = operand_subword (op, TARGET_BIG_ENDIAN, 0, mode);
1734           break;
1735
1736         default:
1737           gcc_unreachable ();
1738         }
1739
1740       /* The high part of CR <- GPR moves must be done after the low part.  */
1741       operands [i + 4] = lo;
1742       operands [i + 2] = hi;
1743     }
1744
1745   if (reg_mentioned_p (operands[2], operands[5])
1746       || GET_CODE (operands[2]) == ZERO_EXTRACT
1747       || GET_CODE (operands[4]) == ZERO_EXTRACT)
1748     {
1749       rtx tmp;
1750
1751       /* Overlapping register pairs -- make sure we don't
1752          early-clobber ourselves.  */
1753       tmp = operands[2];
1754       operands[2] = operands[4];
1755       operands[4] = tmp;
1756       tmp = operands[3];
1757       operands[3] = operands[5];
1758       operands[5] = tmp;
1759     }
1760
1761 #if DEBUG_SPLIT_WIDE_MOVE
1762   fprintf(stderr, "\033[34m");
1763   debug_rtx (operands[2]);
1764   debug_rtx (operands[3]);
1765   debug_rtx (operands[4]);
1766   debug_rtx (operands[5]);
1767   fprintf(stderr, "\033[0m");
1768 #endif
1769 }
1770
1771 /* Emit a setcc instruction in its entirity.  */
1772
1773 static bool
1774 mep_expand_setcc_1 (enum rtx_code code, rtx dest, rtx op1, rtx op2)
1775 {
1776   rtx tmp;
1777
1778   switch (code)
1779     {
1780     case GT:
1781     case GTU:
1782       tmp = op1, op1 = op2, op2 = tmp;
1783       code = swap_condition (code);
1784       /* FALLTHRU */
1785
1786     case LT:
1787     case LTU:
1788       op1 = force_reg (SImode, op1);
1789       emit_insn (gen_rtx_SET (VOIDmode, dest,
1790                               gen_rtx_fmt_ee (code, SImode, op1, op2)));
1791       return true;
1792
1793     case EQ:
1794       if (op2 != const0_rtx)
1795         op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1796       mep_expand_setcc_1 (LTU, dest, op1, const1_rtx);
1797       return true;
1798
1799     case NE:
1800       /* Branchful sequence:
1801                 mov dest, 0             16-bit
1802                 beq op1, op2, Lover     16-bit (op2 < 16), 32-bit otherwise
1803                 mov dest, 1             16-bit
1804
1805          Branchless sequence:
1806                 add3 tmp, op1, -op2     32-bit (or mov + sub)
1807                 sltu3 tmp, tmp, 1       16-bit
1808                 xor3 dest, tmp, 1       32-bit
1809         */
1810       if (optimize_size && op2 != const0_rtx)
1811         return false;
1812
1813       if (op2 != const0_rtx)
1814         op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN);
1815
1816       op2 = gen_reg_rtx (SImode);
1817       mep_expand_setcc_1 (LTU, op2, op1, const1_rtx);
1818
1819       emit_insn (gen_rtx_SET (VOIDmode, dest,
1820                               gen_rtx_XOR (SImode, op2, const1_rtx)));
1821       return true;
1822
1823     case LE:
1824       if (GET_CODE (op2) != CONST_INT
1825           || INTVAL (op2) == 0x7ffffff)
1826         return false;
1827       op2 = GEN_INT (INTVAL (op2) + 1);
1828       return mep_expand_setcc_1 (LT, dest, op1, op2);
1829
1830     case LEU:
1831       if (GET_CODE (op2) != CONST_INT
1832           || INTVAL (op2) == -1)
1833         return false;
1834       op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) + 1, SImode));
1835       return mep_expand_setcc_1 (LTU, dest, op1, op2);
1836
1837     case GE:
1838       if (GET_CODE (op2) != CONST_INT
1839           || INTVAL (op2) == trunc_int_for_mode (0x80000000, SImode))
1840         return false;
1841       op2 = GEN_INT (INTVAL (op2) - 1);
1842       return mep_expand_setcc_1 (GT, dest, op1, op2);
1843
1844     case GEU:
1845       if (GET_CODE (op2) != CONST_INT
1846           || op2 == const0_rtx)
1847         return false;
1848       op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) - 1, SImode));
1849       return mep_expand_setcc_1 (GTU, dest, op1, op2);
1850
1851     default:
1852       gcc_unreachable ();
1853     }
1854 }
1855
1856 bool
1857 mep_expand_setcc (rtx *operands)
1858 {
1859   rtx dest = operands[0];
1860   enum rtx_code code = GET_CODE (operands[1]);
1861   rtx op0 = operands[2];
1862   rtx op1 = operands[3];
1863
1864   return mep_expand_setcc_1 (code, dest, op0, op1);
1865 }
1866
1867 rtx
1868 mep_expand_cbranch (rtx *operands)
1869 {
1870   enum rtx_code code = GET_CODE (operands[0]);
1871   rtx op0 = operands[1];
1872   rtx op1 = operands[2];
1873   rtx tmp;
1874
1875  restart:
1876   switch (code)
1877     {
1878     case LT:
1879       if (mep_imm4_operand (op1, SImode))
1880         break;
1881
1882       tmp = gen_reg_rtx (SImode);
1883       gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1884       code = NE;
1885       op0 = tmp;
1886       op1 = const0_rtx;
1887       break;
1888
1889     case GE:
1890       if (mep_imm4_operand (op1, SImode))
1891         break;
1892
1893       tmp = gen_reg_rtx (SImode);
1894       gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1));
1895
1896       code = EQ;
1897       op0 = tmp;
1898       op1 = const0_rtx;
1899       break;
1900
1901     case EQ:
1902     case NE:
1903       if (! mep_reg_or_imm4_operand (op1, SImode))
1904         op1 = force_reg (SImode, op1);
1905       break;
1906
1907     case LE:
1908     case GT:
1909       if (GET_CODE (op1) == CONST_INT
1910           && INTVAL (op1) != 0x7fffffff)
1911         {
1912           op1 = GEN_INT (INTVAL (op1) + 1);
1913           code = (code == LE ? LT : GE);
1914           goto restart;
1915         }
1916
1917       tmp = gen_reg_rtx (SImode);
1918       gcc_assert (mep_expand_setcc_1 (LT, tmp, op1, op0));
1919
1920       code = (code == LE ? EQ : NE);
1921       op0 = tmp;
1922       op1 = const0_rtx;
1923       break;
1924
1925     case LTU:
1926       if (op1 == const1_rtx)
1927         {
1928           code = EQ;
1929           op1 = const0_rtx;
1930           break;
1931         }
1932
1933       tmp = gen_reg_rtx (SImode);
1934       gcc_assert (mep_expand_setcc_1 (LTU, tmp, op0, op1));
1935       code = NE;
1936       op0 = tmp;
1937       op1 = const0_rtx;
1938       break;
1939
1940     case LEU:
1941       tmp = gen_reg_rtx (SImode);
1942       if (mep_expand_setcc_1 (LEU, tmp, op0, op1))
1943         code = NE;
1944       else if (mep_expand_setcc_1 (LTU, tmp, op1, op0))
1945         code = EQ;
1946       else
1947         gcc_unreachable ();
1948       op0 = tmp;
1949       op1 = const0_rtx;
1950       break;
1951
1952     case GTU:
1953       tmp = gen_reg_rtx (SImode);
1954       gcc_assert (mep_expand_setcc_1 (GTU, tmp, op0, op1)
1955                   || mep_expand_setcc_1 (LTU, tmp, op1, op0));
1956       code = NE;
1957       op0 = tmp;
1958       op1 = const0_rtx;
1959       break;
1960
1961     case GEU:
1962       tmp = gen_reg_rtx (SImode);
1963       if (mep_expand_setcc_1 (GEU, tmp, op0, op1))
1964         code = NE;
1965       else if (mep_expand_setcc_1 (LTU, tmp, op0, op1))
1966         code = EQ;
1967       else
1968         gcc_unreachable ();
1969       op0 = tmp;
1970       op1 = const0_rtx;
1971       break;
1972
1973     default:
1974       gcc_unreachable ();
1975     }
1976
1977   return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
1978 }
1979
1980 const char *
1981 mep_emit_cbranch (rtx *operands, int ne)
1982 {
1983   if (GET_CODE (operands[1]) == REG)
1984     return ne ? "bne\t%0, %1, %l2" : "beq\t%0, %1, %l2";
1985   else if (INTVAL (operands[1]) == 0)
1986     return ne ? "bnez\t%0, %l2" : "beqz\t%0, %l2";
1987   else
1988     return ne ? "bnei\t%0, %1, %l2" : "beqi\t%0, %1, %l2";
1989 }
1990
1991 void
1992 mep_expand_call (rtx *operands, int returns_value)
1993 {
1994   rtx addr = operands[returns_value];
1995   rtx tp = mep_tp_rtx ();
1996   rtx gp = mep_gp_rtx ();
1997
1998   gcc_assert (GET_CODE (addr) == MEM);
1999
2000   addr = XEXP (addr, 0);
2001
2002   if (! mep_call_address_operand (addr, VOIDmode))
2003     addr = force_reg (SImode, addr);
2004
2005   if (! operands[returns_value+2])
2006     operands[returns_value+2] = const0_rtx;
2007
2008   if (returns_value)
2009     emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
2010                                              operands[3], tp, gp));
2011   else
2012     emit_call_insn (gen_call_internal (addr, operands[1],
2013                                        operands[2], tp, gp));
2014 }
2015 \f
2016 /* Aliasing Support.  */
2017
2018 /* If X is a machine specific address (i.e. a symbol or label being
2019    referenced as a displacement from the GOT implemented using an
2020    UNSPEC), then return the base term.  Otherwise return X.  */
2021
2022 rtx
2023 mep_find_base_term (rtx x)
2024 {
2025   rtx base, term;
2026   int unspec;
2027
2028   if (GET_CODE (x) != PLUS)
2029     return x;
2030   base = XEXP (x, 0);
2031   term = XEXP (x, 1);
2032
2033   if (has_hard_reg_initial_val(Pmode, TP_REGNO)
2034       && base == mep_tp_rtx ())
2035     unspec = UNS_TPREL;
2036   else if (has_hard_reg_initial_val(Pmode, GP_REGNO)
2037            && base == mep_gp_rtx ())
2038     unspec = UNS_GPREL;
2039   else
2040     return x;
2041
2042   if (GET_CODE (term) != CONST)
2043     return x;
2044   term = XEXP (term, 0);
2045
2046   if (GET_CODE (term) != UNSPEC
2047       || XINT (term, 1) != unspec)
2048     return x;
2049
2050   return XVECEXP (term, 0, 0);
2051 }
2052 \f
2053 /* Reload Support.  */
2054
2055 /* Return true if the registers in CLASS cannot represent the change from
2056    modes FROM to TO.  */
2057
2058 bool
2059 mep_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
2060                                enum reg_class regclass)
2061 {
2062   if (from == to)
2063     return false;
2064
2065   /* 64-bit COP regs must remain 64-bit COP regs.  */
2066   if (TARGET_64BIT_CR_REGS
2067       && (regclass == CR_REGS
2068           || regclass == LOADABLE_CR_REGS)
2069       && (GET_MODE_SIZE (to) < 8
2070           || GET_MODE_SIZE (from) < 8))
2071     return true;
2072
2073   return false;
2074 }
2075
2076 #define MEP_NONGENERAL_CLASS(C) (!reg_class_subset_p (C, GENERAL_REGS))
2077
2078 static bool
2079 mep_general_reg (rtx x)
2080 {
2081   while (GET_CODE (x) == SUBREG)
2082     x = XEXP (x, 0);
2083   return GET_CODE (x) == REG && GR_REGNO_P (REGNO (x));
2084 }
2085
2086 static bool
2087 mep_nongeneral_reg (rtx x)
2088 {
2089   while (GET_CODE (x) == SUBREG)
2090     x = XEXP (x, 0);
2091   return (GET_CODE (x) == REG
2092           && !GR_REGNO_P (REGNO (x)) && REGNO (x) < FIRST_PSEUDO_REGISTER);
2093 }
2094
2095 static bool
2096 mep_general_copro_reg (rtx x)
2097 {
2098   while (GET_CODE (x) == SUBREG)
2099     x = XEXP (x, 0);
2100   return (GET_CODE (x) == REG && CR_REGNO_P (REGNO (x)));
2101 }
2102
2103 static bool
2104 mep_nonregister (rtx x)
2105 {
2106   while (GET_CODE (x) == SUBREG)
2107     x = XEXP (x, 0);
2108   return (GET_CODE (x) != REG || REGNO (x) >= FIRST_PSEUDO_REGISTER);
2109 }
2110
2111 #define DEBUG_RELOAD 0
2112
2113 /* Return the secondary reload class needed for moving value X to or
2114    from a register in coprocessor register class CLASS.  */
2115
2116 static enum reg_class
2117 mep_secondary_copro_reload_class (enum reg_class rclass, rtx x)
2118 {
2119   if (mep_general_reg (x))
2120     /* We can do the move directly if mep_have_core_copro_moves_p,
2121        otherwise we need to go through memory.  Either way, no secondary
2122        register is needed.  */
2123     return NO_REGS;
2124
2125   if (mep_general_copro_reg (x))
2126     {
2127       /* We can do the move directly if mep_have_copro_copro_moves_p.  */
2128       if (mep_have_copro_copro_moves_p)
2129         return NO_REGS;
2130
2131       /* Otherwise we can use a temporary if mep_have_core_copro_moves_p.  */
2132       if (mep_have_core_copro_moves_p)
2133         return GENERAL_REGS;
2134
2135       /* Otherwise we need to do it through memory.  No secondary
2136          register is needed.  */
2137       return NO_REGS;
2138     }
2139
2140   if (reg_class_subset_p (rclass, LOADABLE_CR_REGS)
2141       && constraint_satisfied_p (x, CONSTRAINT_U))
2142     /* X is a memory value that we can access directly.  */
2143     return NO_REGS;
2144
2145   /* We have to move X into a GPR first and then copy it to
2146      the coprocessor register.  The move from the GPR to the
2147      coprocessor might be done directly or through memory,
2148      depending on mep_have_core_copro_moves_p. */
2149   return GENERAL_REGS;
2150 }
2151
2152 /* Copying X to register in RCLASS.  */
2153
2154 int
2155 mep_secondary_input_reload_class (enum reg_class rclass,
2156                                   enum machine_mode mode ATTRIBUTE_UNUSED,
2157                                   rtx x)
2158 {
2159   int rv = NO_REGS;
2160
2161 #if DEBUG_RELOAD
2162   fprintf (stderr, "secondary input reload copy to %s %s from ", reg_class_names[rclass], mode_name[mode]);
2163   debug_rtx (x);
2164 #endif
2165
2166   if (reg_class_subset_p (rclass, CR_REGS))
2167     rv = mep_secondary_copro_reload_class (rclass, x);
2168   else if (MEP_NONGENERAL_CLASS (rclass)
2169            && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2170     rv = GENERAL_REGS;
2171
2172 #if DEBUG_RELOAD
2173   fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2174 #endif
2175   return rv;
2176 }
2177
2178 /* Copying register in RCLASS to X.  */
2179
2180 int
2181 mep_secondary_output_reload_class (enum reg_class rclass,
2182                                    enum machine_mode mode ATTRIBUTE_UNUSED,
2183                                    rtx x)
2184 {
2185   int rv = NO_REGS;
2186
2187 #if DEBUG_RELOAD
2188   fprintf (stderr, "secondary output reload copy from %s %s to ", reg_class_names[rclass], mode_name[mode]);
2189   debug_rtx (x);
2190 #endif
2191
2192   if (reg_class_subset_p (rclass, CR_REGS))
2193     rv = mep_secondary_copro_reload_class (rclass, x);
2194   else if (MEP_NONGENERAL_CLASS (rclass)
2195            && (mep_nonregister (x) || mep_nongeneral_reg (x)))
2196     rv = GENERAL_REGS;
2197
2198 #if DEBUG_RELOAD
2199   fprintf (stderr, " - requires %s\n", reg_class_names[rv]);
2200 #endif
2201
2202   return rv;
2203 }
2204
2205 /* Implement SECONDARY_MEMORY_NEEDED.  */
2206
2207 bool
2208 mep_secondary_memory_needed (enum reg_class rclass1, enum reg_class rclass2,
2209                              enum machine_mode mode ATTRIBUTE_UNUSED)
2210 {
2211   if (!mep_have_core_copro_moves_p)
2212     {
2213       if (reg_classes_intersect_p (rclass1, CR_REGS)
2214           && reg_classes_intersect_p (rclass2, GENERAL_REGS))
2215         return true;
2216       if (reg_classes_intersect_p (rclass2, CR_REGS)
2217           && reg_classes_intersect_p (rclass1, GENERAL_REGS))
2218         return true;
2219       if (!mep_have_copro_copro_moves_p
2220           && reg_classes_intersect_p (rclass1, CR_REGS)
2221           && reg_classes_intersect_p (rclass2, CR_REGS))
2222         return true;
2223     }
2224   return false;
2225 }
2226
2227 void
2228 mep_expand_reload (rtx *operands, enum machine_mode mode)
2229 {
2230   /* There are three cases for each direction:
2231      register, farsym
2232      control, farsym
2233      control, nearsym */
2234
2235   int s0 = mep_section_tag (operands[0]) == 'f';
2236   int s1 = mep_section_tag (operands[1]) == 'f';
2237   int c0 = mep_nongeneral_reg (operands[0]);
2238   int c1 = mep_nongeneral_reg (operands[1]);
2239   int which = (s0 ? 20:0) + (c0 ? 10:0) + (s1 ? 2:0) + (c1 ? 1:0);
2240
2241 #if DEBUG_RELOAD
2242   fprintf (stderr, "expand_reload %s\n", mode_name[mode]);
2243   debug_rtx (operands[0]);
2244   debug_rtx (operands[1]);
2245 #endif
2246
2247   switch (which)
2248     {
2249     case 00: /* Don't know why this gets here.  */
2250     case 02: /* general = far */
2251       emit_move_insn (operands[0], operands[1]);
2252       return;
2253
2254     case 10: /* cr = mem */
2255     case 11: /* cr = cr */
2256     case 01: /* mem = cr */
2257     case 12: /* cr = far */
2258       emit_move_insn (operands[2], operands[1]);
2259       emit_move_insn (operands[0], operands[2]);
2260       return;
2261
2262     case 20: /* far = general */
2263       emit_move_insn (operands[2], XEXP (operands[1], 0));
2264       emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2]));
2265       return;
2266
2267     case 21: /* far = cr */
2268     case 22: /* far = far */
2269     default:
2270       fprintf (stderr, "unsupported expand reload case %02d for mode %s\n",
2271                which, mode_name[mode]);
2272       debug_rtx (operands[0]);
2273       debug_rtx (operands[1]);
2274       gcc_unreachable ();
2275     }
2276 }
2277
2278 /* Implement PREFERRED_RELOAD_CLASS.  See whether X is a constant that
2279    can be moved directly into registers 0 to 7, but not into the rest.
2280    If so, and if the required class includes registers 0 to 7, restrict
2281    it to those registers.  */
2282
2283 enum reg_class
2284 mep_preferred_reload_class (rtx x, enum reg_class rclass)
2285 {
2286   switch (GET_CODE (x))
2287     {
2288     case CONST_INT:
2289       if (INTVAL (x) >= 0x10000
2290           && INTVAL (x) < 0x01000000
2291           && (INTVAL (x) & 0xffff) != 0
2292           && reg_class_subset_p (TPREL_REGS, rclass))
2293         rclass = TPREL_REGS;
2294       break;
2295
2296     case CONST:
2297     case SYMBOL_REF:
2298     case LABEL_REF:
2299       if (mep_section_tag (x) != 'f'
2300           && reg_class_subset_p (TPREL_REGS, rclass))
2301         rclass = TPREL_REGS;
2302       break;
2303
2304     default:
2305       break;
2306     }
2307   return rclass;
2308 }
2309 \f
2310 /* Implement REGISTER_MOVE_COST.  Return 2 for direct single-register
2311    moves, 4 for direct double-register moves, and 1000 for anything
2312    that requires a temporary register or temporary stack slot.  */
2313
2314 int
2315 mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_class to)
2316 {
2317   if (mep_have_copro_copro_moves_p
2318       && reg_class_subset_p (from, CR_REGS)
2319       && reg_class_subset_p (to, CR_REGS))
2320     {
2321       if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2322         return 4;
2323       return 2;
2324     }
2325   if (reg_class_subset_p (from, CR_REGS)
2326       && reg_class_subset_p (to, CR_REGS))
2327     {
2328       if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2329         return 8;
2330       return 4;
2331     }
2332   if (reg_class_subset_p (from, CR_REGS)
2333       || reg_class_subset_p (to, CR_REGS))
2334     {
2335       if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2336         return 4;
2337       return 2;
2338     }
2339   if (mep_secondary_memory_needed (from, to, mode))
2340     return 1000;
2341   if (MEP_NONGENERAL_CLASS (from) && MEP_NONGENERAL_CLASS (to))
2342     return 1000;
2343
2344   if (GET_MODE_SIZE (mode) > 4)
2345     return 4;
2346
2347   return 2;
2348 }
2349
2350 \f
2351 /* Functions to save and restore machine-specific function data.  */
2352
2353 static struct machine_function *
2354 mep_init_machine_status (void)
2355 {
2356   struct machine_function *f;
2357
2358   f = (struct machine_function *) ggc_alloc_cleared (sizeof (struct machine_function));
2359
2360   return f;
2361 }
2362
2363 static rtx
2364 mep_allocate_initial_value (rtx reg)
2365 {
2366   int rss;
2367
2368   if (GET_CODE (reg) != REG)
2369     return NULL_RTX;
2370
2371   if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
2372     return NULL_RTX;
2373
2374   /* In interrupt functions, the "initial" values of $gp and $tp are
2375      provided by the prologue.  They are not necessarily the same as
2376      the values that the caller was using.  */
2377   if (REGNO (reg) == TP_REGNO || REGNO (reg) == GP_REGNO)
2378     if (mep_interrupt_p ())
2379       return NULL_RTX;
2380
2381   if (! cfun->machine->reg_save_slot[REGNO(reg)])
2382     {
2383       cfun->machine->reg_save_size += 4;
2384       cfun->machine->reg_save_slot[REGNO(reg)] = cfun->machine->reg_save_size;
2385     }
2386
2387   rss = cfun->machine->reg_save_slot[REGNO(reg)];
2388   return gen_rtx_MEM (SImode, plus_constant (arg_pointer_rtx, -rss));
2389 }
2390
2391 rtx
2392 mep_return_addr_rtx (int count)
2393 {
2394   if (count != 0)
2395     return const0_rtx;
2396
2397   return get_hard_reg_initial_val (Pmode, LP_REGNO);
2398 }
2399
2400 static rtx
2401 mep_tp_rtx (void)
2402 {
2403   return get_hard_reg_initial_val (Pmode, TP_REGNO);
2404 }
2405
2406 static rtx
2407 mep_gp_rtx (void)
2408 {
2409   return get_hard_reg_initial_val (Pmode, GP_REGNO);
2410 }
2411
2412 static bool
2413 mep_interrupt_p (void)
2414 {
2415   if (cfun->machine->interrupt_handler == 0)
2416     {
2417       int interrupt_handler
2418         = (lookup_attribute ("interrupt",
2419                              DECL_ATTRIBUTES (current_function_decl))
2420            != NULL_TREE);
2421       cfun->machine->interrupt_handler = interrupt_handler ? 2 : 1;
2422     }
2423   return cfun->machine->interrupt_handler == 2;
2424 }
2425
2426 static bool
2427 mep_disinterrupt_p (void)
2428 {
2429   if (cfun->machine->disable_interrupts == 0)
2430     {
2431       int disable_interrupts
2432         = (lookup_attribute ("disinterrupt",
2433                              DECL_ATTRIBUTES (current_function_decl))
2434            != NULL_TREE);
2435       cfun->machine->disable_interrupts = disable_interrupts ? 2 : 1;
2436     }
2437   return cfun->machine->disable_interrupts == 2;
2438 }
2439
2440 \f
2441 /* Frame/Epilog/Prolog Related.  */
2442
2443 static bool
2444 mep_reg_set_p (rtx reg, rtx insn)
2445 {
2446   /* Similar to reg_set_p in rtlanal.c, but we ignore calls */
2447   if (INSN_P (insn))
2448     {
2449       if (FIND_REG_INC_NOTE (insn, reg))
2450         return true;
2451       insn = PATTERN (insn);
2452     }
2453
2454   if (GET_CODE (insn) == SET
2455       && GET_CODE (XEXP (insn, 0)) == REG
2456       && GET_CODE (XEXP (insn, 1)) == REG
2457       && REGNO (XEXP (insn, 0)) == REGNO (XEXP (insn, 1)))
2458     return false;
2459
2460   return set_of (reg, insn) != NULL_RTX;
2461 }
2462
2463
2464 #define MEP_SAVES_UNKNOWN 0
2465 #define MEP_SAVES_YES 1
2466 #define MEP_SAVES_MAYBE 2
2467 #define MEP_SAVES_NO 3
2468
2469 static bool
2470 mep_reg_set_in_function (int regno)
2471 {
2472   rtx reg, insn;
2473
2474   if (mep_interrupt_p () && df_regs_ever_live_p(regno))
2475     return true;
2476
2477   if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2478     return true;
2479
2480   push_topmost_sequence ();
2481   insn = get_insns ();
2482   pop_topmost_sequence ();
2483
2484   if (!insn)
2485     return false;
2486
2487   reg = gen_rtx_REG (SImode, regno);
2488
2489   for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
2490     if (INSN_P (insn) && mep_reg_set_p (reg, insn))
2491       return true;
2492   return false;
2493 }
2494
2495 static bool
2496 mep_asm_without_operands_p (void)
2497 {
2498   if (cfun->machine->asms_without_operands == 0)
2499     {
2500       rtx insn;
2501
2502       push_topmost_sequence ();
2503       insn = get_insns ();
2504       pop_topmost_sequence ();
2505
2506       cfun->machine->asms_without_operands = 1;
2507       while (insn)
2508         {
2509           if (INSN_P (insn)
2510               && GET_CODE (PATTERN (insn)) == ASM_INPUT)
2511             {
2512               cfun->machine->asms_without_operands = 2;
2513               break;
2514             }
2515           insn = NEXT_INSN (insn);
2516         }
2517
2518     }
2519   return cfun->machine->asms_without_operands == 2;
2520 }
2521
2522 /* Interrupt functions save/restore every call-preserved register, and
2523    any call-used register it uses (or all if it calls any function,
2524    since they may get clobbered there too).  Here we check to see
2525    which call-used registers need saving.  */
2526
2527 #define IVC2_ISAVED_REG(r) (TARGET_IVC2 \
2528                            && (r == FIRST_CCR_REGNO + 1 \
2529                                || (r >= FIRST_CCR_REGNO + 8 && r <= FIRST_CCR_REGNO + 11) \
2530                                || (r >= FIRST_CCR_REGNO + 16 && r <= FIRST_CCR_REGNO + 31)))
2531
2532 static bool
2533 mep_interrupt_saved_reg (int r)
2534 {
2535   if (!mep_interrupt_p ())
2536     return false;
2537   if (r == REGSAVE_CONTROL_TEMP
2538       || (TARGET_64BIT_CR_REGS && TARGET_COP && r == REGSAVE_CONTROL_TEMP+1))
2539     return true;
2540   if (mep_asm_without_operands_p ()
2541       && (!fixed_regs[r]
2542           || (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO || r == LP_REGNO)
2543           || IVC2_ISAVED_REG (r)))
2544     return true;
2545   if (!current_function_is_leaf)
2546     /* Function calls mean we need to save $lp.  */
2547     if (r == LP_REGNO || IVC2_ISAVED_REG (r))
2548       return true;
2549   if (!current_function_is_leaf || cfun->machine->doloop_tags > 0)
2550     /* The interrupt handler might use these registers for repeat blocks,
2551        or it might call a function that does so.  */
2552     if (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO)
2553       return true;
2554   if (current_function_is_leaf && call_used_regs[r] && !df_regs_ever_live_p(r))
2555     return false;
2556   /* Functions we call might clobber these.  */
2557   if (call_used_regs[r] && !fixed_regs[r])
2558     return true;
2559   /* Additional registers that need to be saved for IVC2.  */
2560   if (IVC2_ISAVED_REG (r))
2561     return true;
2562
2563   return false;
2564 }
2565
2566 static bool
2567 mep_call_saves_register (int r)
2568 {
2569   if (! cfun->machine->frame_locked)
2570     {
2571       int rv = MEP_SAVES_NO;
2572
2573       if (cfun->machine->reg_save_slot[r])
2574         rv = MEP_SAVES_YES;
2575       else if (r == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2576         rv = MEP_SAVES_YES;
2577       else if (r == FRAME_POINTER_REGNUM && frame_pointer_needed)
2578         rv = MEP_SAVES_YES;
2579       else if ((!call_used_regs[r] || r == LP_REGNO) && df_regs_ever_live_p(r))
2580         rv = MEP_SAVES_YES;
2581       else if (crtl->calls_eh_return && (r == 10 || r == 11))
2582         /* We need these to have stack slots so that they can be set during
2583            unwinding.  */
2584         rv = MEP_SAVES_YES;
2585       else if (mep_interrupt_saved_reg (r))
2586         rv = MEP_SAVES_YES;
2587       cfun->machine->reg_saved[r] = rv;
2588     }
2589   return cfun->machine->reg_saved[r] == MEP_SAVES_YES;
2590 }
2591
2592 /* Return true if epilogue uses register REGNO.  */
2593
2594 bool
2595 mep_epilogue_uses (int regno)
2596 {
2597   /* Since $lp is a call-saved register, the generic code will normally
2598      mark it used in the epilogue if it needs to be saved and restored.
2599      However, when profiling is enabled, the profiling code will implicitly
2600      clobber $11.  This case has to be handled specially both here and in
2601      mep_call_saves_register.  */
2602   if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0))
2603     return true;
2604   /* Interrupt functions save/restore pretty much everything.  */
2605   return (reload_completed && mep_interrupt_saved_reg (regno));
2606 }
2607
2608 static int
2609 mep_reg_size (int regno)
2610 {
2611   if (CR_REGNO_P (regno) && TARGET_64BIT_CR_REGS)
2612     return 8;
2613   return 4;
2614 }
2615
2616 /* Worker function for TARGET_CAN_ELIMINATE.  */
2617
2618 bool
2619 mep_can_eliminate (const int from, const int to)
2620 {
2621   return  (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
2622            ? ! frame_pointer_needed
2623            : true);
2624 }
2625
2626 int
2627 mep_elimination_offset (int from, int to)
2628 {
2629   int reg_save_size;
2630   int i;
2631   int frame_size = get_frame_size () + crtl->outgoing_args_size;
2632   int total_size;
2633
2634   if (!cfun->machine->frame_locked)
2635     memset (cfun->machine->reg_saved, 0, sizeof (cfun->machine->reg_saved));
2636
2637   /* We don't count arg_regs_to_save in the arg pointer offset, because
2638      gcc thinks the arg pointer has moved along with the saved regs.
2639      However, we do count it when we adjust $sp in the prologue.  */
2640   reg_save_size = 0;
2641   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2642     if (mep_call_saves_register (i))
2643       reg_save_size += mep_reg_size (i);
2644
2645   if (reg_save_size % 8)
2646     cfun->machine->regsave_filler = 8 - (reg_save_size % 8);
2647   else
2648     cfun->machine->regsave_filler = 0;
2649
2650   /* This is what our total stack adjustment looks like.  */
2651   total_size = (reg_save_size + frame_size + cfun->machine->regsave_filler);
2652
2653   if (total_size % 8)
2654     cfun->machine->frame_filler = 8 - (total_size % 8);
2655   else
2656     cfun->machine->frame_filler = 0;
2657
2658
2659   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2660     return reg_save_size + cfun->machine->regsave_filler;
2661
2662   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2663     return cfun->machine->frame_filler + frame_size;
2664
2665   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2666     return reg_save_size + cfun->machine->regsave_filler + cfun->machine->frame_filler + frame_size;
2667
2668   gcc_unreachable ();
2669 }
2670
2671 static rtx
2672 F (rtx x)
2673 {
2674   RTX_FRAME_RELATED_P (x) = 1;
2675   return x;
2676 }
2677
2678 /* Since the prologue/epilogue code is generated after optimization,
2679    we can't rely on gcc to split constants for us.  So, this code
2680    captures all the ways to add a constant to a register in one logic
2681    chunk, including optimizing away insns we just don't need.  This
2682    makes the prolog/epilog code easier to follow.  */
2683 static void
2684 add_constant (int dest, int src, int value, int mark_frame)
2685 {
2686   rtx insn;
2687   int hi, lo;
2688
2689   if (src == dest && value == 0)
2690     return;
2691
2692   if (value == 0)
2693     {
2694       insn = emit_move_insn (gen_rtx_REG (SImode, dest),
2695                              gen_rtx_REG (SImode, src));
2696       if (mark_frame)
2697         RTX_FRAME_RELATED_P(insn) = 1;
2698       return;
2699     }
2700
2701   if (value >= -32768 && value <= 32767)
2702     {
2703       insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2704                                     gen_rtx_REG (SImode, src),
2705                                     GEN_INT (value)));
2706       if (mark_frame)
2707         RTX_FRAME_RELATED_P(insn) = 1;
2708       return;
2709     }
2710
2711   /* Big constant, need to use a temp register.  We use
2712      REGSAVE_CONTROL_TEMP because it's call clobberable (the reg save
2713      area is always small enough to directly add to).  */
2714
2715   hi = trunc_int_for_mode (value & 0xffff0000, SImode);
2716   lo = value & 0xffff;
2717
2718   insn = emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2719                          GEN_INT (hi));
2720
2721   if (lo)
2722     {
2723       insn = emit_insn (gen_iorsi3 (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2724                                     gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2725                                     GEN_INT (lo)));
2726     }
2727
2728   insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest),
2729                                 gen_rtx_REG (SImode, src),
2730                                 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP)));
2731   if (mark_frame)
2732     {
2733       RTX_FRAME_RELATED_P(insn) = 1;
2734       add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2735                     gen_rtx_SET (SImode,
2736                                  gen_rtx_REG (SImode, dest),
2737                                  gen_rtx_PLUS (SImode,
2738                                                gen_rtx_REG (SImode, dest),
2739                                                GEN_INT (value))));
2740     }
2741 }
2742
2743 static bool
2744 mep_function_uses_sp (void)
2745 {
2746   rtx insn;
2747   struct sequence_stack *seq;
2748   rtx sp = gen_rtx_REG (SImode, SP_REGNO);
2749
2750   insn = get_insns ();
2751   for (seq = crtl->emit.sequence_stack;
2752        seq;
2753        insn = seq->first, seq = seq->next);
2754
2755   while (insn)
2756     {
2757       if (mep_mentioned_p (insn, sp, 0))
2758         return true;
2759       insn = NEXT_INSN (insn);
2760     }
2761   return false;
2762 }
2763
2764 /* Move SRC to DEST.  Mark the move as being potentially dead if
2765    MAYBE_DEAD_P.  */
2766
2767 static rtx
2768 maybe_dead_move (rtx dest, rtx src, bool ATTRIBUTE_UNUSED maybe_dead_p)
2769 {
2770   rtx insn = emit_move_insn (dest, src);
2771 #if 0
2772   if (maybe_dead_p)
2773     REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
2774 #endif
2775   return insn;
2776 }
2777
2778 /* Used for interrupt functions, which can't assume that $tp and $gp
2779    contain the correct pointers.  */
2780
2781 static void
2782 mep_reload_pointer (int regno, const char *symbol)
2783 {
2784   rtx reg, sym;
2785
2786   if (!df_regs_ever_live_p(regno) && current_function_is_leaf)
2787     return;
2788
2789   reg = gen_rtx_REG (SImode, regno);
2790   sym = gen_rtx_SYMBOL_REF (SImode, symbol);
2791   emit_insn (gen_movsi_topsym_s (reg, sym));
2792   emit_insn (gen_movsi_botsym_s (reg, reg, sym));
2793 }
2794
2795 /* Assign save slots for any register not already saved.  DImode
2796    registers go at the end of the reg save area; the rest go at the
2797    beginning.  This is for alignment purposes.  Returns true if a frame
2798    is really needed.  */
2799 static bool
2800 mep_assign_save_slots (int reg_save_size)
2801 {
2802   bool really_need_stack_frame = false;
2803   int di_ofs = 0;
2804   int i;
2805
2806   for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2807     if (mep_call_saves_register(i))
2808       {
2809         int regsize = mep_reg_size (i);
2810
2811         if ((i != TP_REGNO && i != GP_REGNO && i != LP_REGNO)
2812             || mep_reg_set_in_function (i))
2813           really_need_stack_frame = true;
2814
2815         if (cfun->machine->reg_save_slot[i])
2816           continue;
2817
2818         if (regsize < 8)
2819           {
2820             cfun->machine->reg_save_size += regsize;
2821             cfun->machine->reg_save_slot[i] = cfun->machine->reg_save_size;
2822           }
2823         else
2824           {
2825             cfun->machine->reg_save_slot[i] = reg_save_size - di_ofs;
2826             di_ofs += 8;
2827           }
2828       }
2829   cfun->machine->frame_locked = 1;
2830   return really_need_stack_frame;
2831 }
2832
2833 void
2834 mep_expand_prologue (void)
2835 {
2836   int i, rss, sp_offset = 0;
2837   int reg_save_size;
2838   int frame_size;
2839   int really_need_stack_frame = frame_size;
2840
2841   /* We must not allow register renaming in interrupt functions,
2842      because that invalidates the correctness of the set of call-used
2843      registers we're going to save/restore.  */
2844   mep_set_leaf_registers (mep_interrupt_p () ? 0 : 1);
2845
2846   if (mep_disinterrupt_p ())
2847     emit_insn (gen_mep_disable_int ());
2848
2849   cfun->machine->mep_frame_pointer_needed = frame_pointer_needed;
2850
2851   reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2852   frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2853
2854   really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2855
2856   sp_offset = reg_save_size;
2857   if (sp_offset + frame_size < 128)
2858     sp_offset += frame_size ;
2859
2860   add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2861
2862   for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2863     if (mep_call_saves_register(i))
2864       {
2865         rtx mem;
2866         bool maybe_dead_p;
2867         enum machine_mode rmode;
2868
2869         rss = cfun->machine->reg_save_slot[i];
2870
2871         if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2872             && (!mep_reg_set_in_function (i)
2873                 && !mep_interrupt_p ()))
2874           continue;
2875
2876         if (mep_reg_size (i) == 8)
2877           rmode = DImode;
2878         else
2879           rmode = SImode;
2880
2881         /* If there is a pseudo associated with this register's initial value,
2882            reload might have already spilt it to the stack slot suggested by
2883            ALLOCATE_INITIAL_VALUE.  The moves emitted here can then be safely
2884            deleted as dead.  */
2885         mem = gen_rtx_MEM (rmode,
2886                            plus_constant (stack_pointer_rtx, sp_offset - rss));
2887         maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2888
2889         if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2890           F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2891         else if (rmode == DImode)
2892           {
2893             rtx insn;
2894             int be = TARGET_BIG_ENDIAN ? 4 : 0;
2895
2896             mem = gen_rtx_MEM (SImode,
2897                                plus_constant (stack_pointer_rtx, sp_offset - rss + be));
2898
2899             maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2900                              gen_rtx_REG (SImode, i),
2901                              maybe_dead_p);
2902             maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2903                              gen_rtx_ZERO_EXTRACT (SImode,
2904                                                    gen_rtx_REG (DImode, i),
2905                                                    GEN_INT (32),
2906                                                    GEN_INT (32)),
2907                              maybe_dead_p);
2908             insn = maybe_dead_move (mem,
2909                                     gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2910                                     maybe_dead_p);
2911             RTX_FRAME_RELATED_P (insn) = 1;
2912             
2913             add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2914                           gen_rtx_SET (VOIDmode,
2915                                        copy_rtx (mem),
2916                                        gen_rtx_REG (rmode, i)));
2917             mem = gen_rtx_MEM (SImode,
2918                                plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be)));
2919             insn = maybe_dead_move (mem,
2920                                     gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2921                                     maybe_dead_p);
2922           }
2923         else
2924           {
2925             rtx insn;
2926             maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2927                              gen_rtx_REG (rmode, i),
2928                              maybe_dead_p);
2929             insn = maybe_dead_move (mem,
2930                                     gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2931                                     maybe_dead_p);
2932             RTX_FRAME_RELATED_P (insn) = 1;
2933             
2934             add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2935                           gen_rtx_SET (VOIDmode,
2936                                        copy_rtx (mem),
2937                                        gen_rtx_REG (rmode, i)));
2938           }
2939       }
2940   
2941   if (frame_pointer_needed)
2942     {
2943       /* We've already adjusted down by sp_offset.  Total $sp change
2944          is reg_save_size + frame_size.  We want a net change here of
2945          just reg_save_size.  */
2946       add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2947     }
2948
2949   add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2950
2951   if (mep_interrupt_p ())
2952     {
2953       mep_reload_pointer(GP_REGNO, "__sdabase");
2954       mep_reload_pointer(TP_REGNO, "__tpbase");
2955     }
2956 }
2957
2958 static void
2959 mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2960 {
2961   int local = hwi_local;
2962   int frame_size = local + crtl->outgoing_args_size;
2963   int reg_save_size;
2964   int ffill;
2965   int i, sp, skip;
2966   int sp_offset;
2967   int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2968
2969   reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2970   frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2971   sp_offset = reg_save_size + frame_size;
2972
2973   ffill = cfun->machine->frame_filler;
2974
2975   if (cfun->machine->mep_frame_pointer_needed)
2976     reg_names[FP_REGNO] = "$fp";
2977   else
2978     reg_names[FP_REGNO] = "$8";
2979
2980   if (sp_offset == 0)
2981     return;
2982
2983   if (debug_info_level == DINFO_LEVEL_NONE)
2984     {
2985       fprintf (file, "\t# frame: %d", sp_offset);
2986       if (reg_save_size)
2987         fprintf (file, "   %d regs", reg_save_size);
2988       if (local)
2989         fprintf (file, "   %d locals", local);
2990       if (crtl->outgoing_args_size)
2991         fprintf (file, "   %d args", crtl->outgoing_args_size);
2992       fprintf (file, "\n");
2993       return;
2994     }
2995
2996   fprintf (file, "\t#\n");
2997   fprintf (file, "\t# Initial Frame Information:\n");
2998   if (sp_offset || !frame_pointer_needed)
2999     fprintf (file, "\t# Entry   ---------- 0\n");
3000
3001   /* Sort registers by save slots, so they're printed in the order
3002      they appear in memory, not the order they're saved in.  */
3003   for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
3004     slot_map[si] = si;
3005   for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
3006     for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
3007       if (cfun->machine->reg_save_slot[slot_map[si]]
3008           > cfun->machine->reg_save_slot[slot_map[sj]])
3009         {
3010           int t = slot_map[si];
3011           slot_map[si] = slot_map[sj];
3012           slot_map[sj] = t;
3013         }
3014
3015   sp = 0;
3016   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3017     {
3018       int rsize;
3019       int r = slot_map[i];
3020       int rss = cfun->machine->reg_save_slot[r];
3021
3022       if (!mep_call_saves_register (r))
3023         continue;
3024
3025       if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
3026           && (!mep_reg_set_in_function (r)
3027               && !mep_interrupt_p ()))
3028         continue;
3029
3030       rsize = mep_reg_size(r);
3031       skip = rss - (sp+rsize);
3032       if (skip)
3033         fprintf (file, "\t#         %3d bytes for alignment\n", skip);
3034       fprintf (file, "\t#         %3d bytes for saved %-3s   %3d($sp)\n",
3035                rsize, reg_names[r], sp_offset - rss);
3036       sp = rss;
3037     }
3038
3039   skip = reg_save_size - sp;
3040   if (skip)
3041     fprintf (file, "\t#         %3d bytes for alignment\n", skip);
3042
3043   if (frame_pointer_needed)
3044     fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
3045   if (local)
3046     fprintf (file, "\t#         %3d bytes for local vars\n", local);
3047   if (ffill)
3048     fprintf (file, "\t#         %3d bytes for alignment\n", ffill);
3049   if (crtl->outgoing_args_size)
3050     fprintf (file, "\t#         %3d bytes for outgoing args\n",
3051              crtl->outgoing_args_size);
3052   fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
3053   fprintf (file, "\t#\n");
3054 }
3055
3056
3057 static int mep_prevent_lp_restore = 0;
3058 static int mep_sibcall_epilogue = 0;
3059
3060 void
3061 mep_expand_epilogue (void)
3062 {
3063   int i, sp_offset = 0;
3064   int reg_save_size = 0;
3065   int frame_size;
3066   int lp_temp = LP_REGNO, lp_slot = -1;
3067   int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
3068   int interrupt_handler = mep_interrupt_p ();
3069
3070   if (profile_arc_flag == 2)
3071     emit_insn (gen_mep_bb_trace_ret ());
3072
3073   reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
3074   frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
3075
3076   really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
3077
3078   if (frame_pointer_needed)
3079     {
3080       /* If we have a frame pointer, we won't have a reliable stack
3081          pointer (alloca, you know), so rebase SP from FP */
3082       emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
3083                       gen_rtx_REG (SImode, FP_REGNO));
3084       sp_offset = reg_save_size;
3085     }
3086   else
3087     {
3088       /* SP is right under our local variable space.  Adjust it if
3089          needed.  */
3090       sp_offset = reg_save_size + frame_size;
3091       if (sp_offset >= 128)
3092         {
3093           add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
3094           sp_offset -= frame_size;
3095         }
3096     }
3097
3098   /* This is backwards so that we restore the control and coprocessor
3099      registers before the temporary registers we use to restore
3100      them.  */
3101   for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
3102     if (mep_call_saves_register (i))
3103       {
3104         enum machine_mode rmode;
3105         int rss = cfun->machine->reg_save_slot[i];
3106
3107         if (mep_reg_size (i) == 8)
3108           rmode = DImode;
3109         else
3110           rmode = SImode;
3111
3112         if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
3113             && !(mep_reg_set_in_function (i) || interrupt_handler))
3114           continue;
3115         if (mep_prevent_lp_restore && i == LP_REGNO)
3116           continue;
3117         if (!mep_prevent_lp_restore
3118             && !interrupt_handler
3119             && (i == 10 || i == 11))
3120           continue;
3121   
3122         if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
3123           emit_move_insn (gen_rtx_REG (rmode, i),
3124                           gen_rtx_MEM (rmode,
3125                                        plus_constant (stack_pointer_rtx,
3126                                                       sp_offset-rss)));
3127         else
3128           {
3129             if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
3130               /* Defer this one so we can jump indirect rather than
3131                  copying the RA to $lp and "ret".  EH epilogues
3132                  automatically skip this anyway.  */
3133               lp_slot = sp_offset-rss;
3134             else
3135               {
3136                 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
3137                                 gen_rtx_MEM (rmode,
3138                                              plus_constant (stack_pointer_rtx,
3139                                                             sp_offset-rss)));
3140                 emit_move_insn (gen_rtx_REG (rmode, i),
3141                                 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
3142               }
3143           }
3144       }
3145   if (lp_slot != -1)
3146     {
3147       /* Restore this one last so we know it will be in the temp
3148          register when we return by jumping indirectly via the temp.  */
3149       emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
3150                       gen_rtx_MEM (SImode,
3151                                    plus_constant (stack_pointer_rtx,
3152                                                   lp_slot)));
3153       lp_temp = REGSAVE_CONTROL_TEMP;
3154     }
3155
3156
3157   add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
3158
3159   if (crtl->calls_eh_return && mep_prevent_lp_restore)
3160     emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3161                            gen_rtx_REG (SImode, SP_REGNO),
3162                            cfun->machine->eh_stack_adjust));
3163
3164   if (mep_sibcall_epilogue)
3165     return;
3166
3167   if (mep_disinterrupt_p ())
3168     emit_insn (gen_mep_enable_int ());
3169
3170   if (mep_prevent_lp_restore)
3171     {
3172       emit_jump_insn (gen_eh_return_internal ());
3173       emit_barrier ();
3174     }
3175   else if (interrupt_handler)
3176     emit_jump_insn (gen_mep_reti ());
3177   else
3178     emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3179 }
3180
3181 void
3182 mep_expand_eh_return (rtx *operands)
3183 {
3184   if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3185     {
3186       rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3187       emit_move_insn (ra, operands[0]);
3188       operands[0] = ra;
3189     }
3190
3191   emit_insn (gen_eh_epilogue (operands[0]));
3192 }
3193
3194 void
3195 mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3196 {
3197   cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3198   mep_prevent_lp_restore = 1;
3199   mep_expand_epilogue ();
3200   mep_prevent_lp_restore = 0;
3201 }
3202
3203 void
3204 mep_expand_sibcall_epilogue (void)
3205 {
3206   mep_sibcall_epilogue = 1;
3207   mep_expand_epilogue ();
3208   mep_sibcall_epilogue = 0;
3209 }
3210
3211 static bool
3212 mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3213 {
3214   if (decl == NULL)
3215     return false;
3216
3217   if (mep_section_tag (DECL_RTL (decl)) == 'f')
3218     return false;
3219
3220   /* Can't call to a sibcall from an interrupt or disinterrupt function.  */
3221   if (mep_interrupt_p () || mep_disinterrupt_p ())
3222     return false;
3223
3224   return true;
3225 }
3226
3227 rtx
3228 mep_return_stackadj_rtx (void)
3229 {
3230   return gen_rtx_REG (SImode, 10);
3231 }
3232
3233 rtx
3234 mep_return_handler_rtx (void)
3235 {
3236   return gen_rtx_REG (SImode, LP_REGNO);
3237 }
3238
3239 void
3240 mep_function_profiler (FILE *file)
3241 {
3242   /* Always right at the beginning of the function.  */
3243   fprintf (file, "\t# mep function profiler\n");
3244   fprintf (file, "\tadd\t$sp, -8\n");
3245   fprintf (file, "\tsw\t$0, ($sp)\n");
3246   fprintf (file, "\tldc\t$0, $lp\n");
3247   fprintf (file, "\tsw\t$0, 4($sp)\n");
3248   fprintf (file, "\tbsr\t__mep_mcount\n");
3249   fprintf (file, "\tlw\t$0, 4($sp)\n");
3250   fprintf (file, "\tstc\t$0, $lp\n");
3251   fprintf (file, "\tlw\t$0, ($sp)\n");
3252   fprintf (file, "\tadd\t$sp, 8\n\n");
3253 }
3254
3255 const char *
3256 mep_emit_bb_trace_ret (void)
3257 {
3258   fprintf (asm_out_file, "\t# end of block profiling\n");
3259   fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3260   fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3261   fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3262   fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3263   fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3264   fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3265   fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3266   fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3267   fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3268   return "";
3269 }
3270
3271 #undef SAVE
3272 #undef RESTORE
3273 \f
3274 /* Operand Printing.  */
3275
3276 void
3277 mep_print_operand_address (FILE *stream, rtx address)
3278 {
3279   if (GET_CODE (address) == MEM)
3280     address = XEXP (address, 0);
3281   else
3282     /* cf: gcc.dg/asm-4.c.  */
3283     gcc_assert (GET_CODE (address) == REG);
3284
3285   mep_print_operand (stream, address, 0);
3286 }
3287
3288 static struct
3289 {
3290   char code;
3291   const char *pattern;
3292   const char *format;
3293 }
3294 const conversions[] =
3295 {
3296   { 0, "r", "0" },
3297   { 0, "m+ri", "3(2)" },
3298   { 0, "mr", "(1)" },
3299   { 0, "ms", "(1)" },
3300   { 0, "ml", "(1)" },
3301   { 0, "mLrs", "%lo(3)(2)" },
3302   { 0, "mLr+si", "%lo(4+5)(2)" },
3303   { 0, "m+ru2s", "%tpoff(5)(2)" },
3304   { 0, "m+ru3s", "%sdaoff(5)(2)" },
3305   { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3306   { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3307   { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3308   { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3309   { 0, "mi", "(1)" },
3310   { 0, "m+si", "(2+3)" },
3311   { 0, "m+li", "(2+3)" },
3312   { 0, "i", "0" },
3313   { 0, "s", "0" },
3314   { 0, "+si", "1+2" },
3315   { 0, "+u2si", "%tpoff(3+4)" },
3316   { 0, "+u3si", "%sdaoff(3+4)" },
3317   { 0, "l", "0" },
3318   { 'b', "i", "0" },
3319   { 'B', "i", "0" },
3320   { 'U', "i", "0" },
3321   { 'h', "i", "0" },
3322   { 'h', "Hs", "%hi(1)" },
3323   { 'I', "i", "0" },
3324   { 'I', "u2s", "%tpoff(2)" },
3325   { 'I', "u3s", "%sdaoff(2)" },
3326   { 'I', "+u2si", "%tpoff(3+4)" },
3327   { 'I', "+u3si", "%sdaoff(3+4)" },
3328   { 'J', "i", "0" },
3329   { 'P', "mr", "(1\\+),\\0" },
3330   { 'x', "i", "0" },
3331   { 0, 0, 0 }
3332 };
3333
3334 static int
3335 unique_bit_in (HOST_WIDE_INT i)
3336 {
3337   switch (i & 0xff)
3338     {
3339     case 0x01: case 0xfe: return 0;
3340     case 0x02: case 0xfd: return 1;
3341     case 0x04: case 0xfb: return 2;
3342     case 0x08: case 0xf7: return 3;
3343     case 0x10: case 0x7f: return 4;
3344     case 0x20: case 0xbf: return 5;
3345     case 0x40: case 0xdf: return 6;
3346     case 0x80: case 0xef: return 7;
3347     default:
3348       gcc_unreachable ();
3349     }
3350 }
3351
3352 static int
3353 bit_size_for_clip (HOST_WIDE_INT i)
3354 {
3355   int rv;
3356
3357   for (rv = 0; rv < 31; rv ++)
3358     if (((HOST_WIDE_INT) 1 << rv) > i)
3359       return rv + 1;
3360   gcc_unreachable ();
3361 }
3362
3363 /* Print an operand to a assembler instruction.  */
3364
3365 void
3366 mep_print_operand (FILE *file, rtx x, int code)
3367 {
3368   int i, j;
3369   const char *real_name;
3370
3371   if (code == '<')
3372     {
3373       /* Print a mnemonic to do CR <- CR moves.  Find out which intrinsic
3374          we're using, then skip over the "mep_" part of its name.  */
3375       const struct cgen_insn *insn;
3376
3377       if (mep_get_move_insn (mep_cmov, &insn))
3378         fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3379       else
3380         mep_intrinsic_unavailable (mep_cmov);
3381       return;
3382     }
3383   if (code == 'L')
3384     {
3385       switch (GET_CODE (x))
3386         {
3387         case AND:
3388           fputs ("clr", file);
3389           return;
3390         case IOR:
3391           fputs ("set", file);
3392           return;
3393         case XOR:
3394           fputs ("not", file);
3395           return;
3396         default:
3397           output_operand_lossage ("invalid %%L code");
3398         }
3399     }
3400   if (code == 'M')
3401     {
3402       /* Print the second operand of a CR <- CR move.  If we're using
3403          a two-operand instruction (i.e., a real cmov), then just print
3404          the operand normally.  If we're using a "reg, reg, immediate"
3405          instruction such as caddi3, print the operand followed by a
3406          zero field.  If we're using a three-register instruction,
3407          print the operand twice.  */
3408       const struct cgen_insn *insn;
3409
3410       mep_print_operand (file, x, 0);
3411       if (mep_get_move_insn (mep_cmov, &insn)
3412           && insn_data[insn->icode].n_operands == 3)
3413         {
3414           fputs (", ", file);
3415           if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3416             mep_print_operand (file, x, 0);
3417           else
3418             mep_print_operand (file, const0_rtx, 0);
3419         }
3420       return;
3421     }
3422
3423   encode_pattern (x);
3424   for (i = 0; conversions[i].pattern; i++)
3425     if (conversions[i].code == code
3426         && strcmp(conversions[i].pattern, pattern) == 0)
3427       {
3428         for (j = 0; conversions[i].format[j]; j++)
3429           if (conversions[i].format[j] == '\\')
3430             {
3431               fputc (conversions[i].format[j+1], file);
3432               j++;
3433             }
3434           else if (ISDIGIT(conversions[i].format[j]))
3435             {
3436               rtx r = patternr[conversions[i].format[j] - '0'];
3437               switch (GET_CODE (r))
3438                 {
3439                 case REG:
3440                   fprintf (file, "%s", reg_names [REGNO (r)]);
3441                   break;
3442                 case CONST_INT:
3443                   switch (code)
3444                     {
3445                     case 'b':
3446                       fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3447                       break;
3448                     case 'B':
3449                       fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3450                       break;
3451                     case 'h':
3452                       fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3453                       break;
3454                     case 'U':
3455                       fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3456                       break;
3457                     case 'J':
3458                       fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3459                       break;
3460                     case 'x':
3461                       if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3462                           && !(INTVAL (r) & 0xff))
3463                         fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3464                       else
3465                         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3466                       break;
3467                     case 'I':
3468                       if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3469                           && conversions[i].format[j+1] == 0)
3470                         {
3471                           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3472                           fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3473                         }
3474                       else
3475                         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3476                       break;
3477                     default:
3478                       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3479                       break;
3480                     }
3481                   break;
3482                 case CONST_DOUBLE:
3483                   fprintf(file, "[const_double 0x%lx]",
3484                           (unsigned long) CONST_DOUBLE_HIGH(r));
3485                   break;
3486                 case SYMBOL_REF:
3487                   real_name = TARGET_STRIP_NAME_ENCODING (XSTR (r, 0));
3488                   assemble_name (file, real_name);
3489                   break;
3490                 case LABEL_REF:
3491                   output_asm_label (r);
3492                   break;
3493                 default:
3494                   fprintf (stderr, "don't know how to print this operand:");
3495                   debug_rtx (r);
3496                   gcc_unreachable ();
3497                 }
3498             }
3499           else
3500             {
3501               if (conversions[i].format[j] == '+'
3502                   && (!code || code == 'I')
3503                   && ISDIGIT (conversions[i].format[j+1])
3504                   && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3505                   && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3506                 continue;
3507               fputc(conversions[i].format[j], file);
3508             }
3509         break;
3510       }
3511   if (!conversions[i].pattern)
3512     {
3513       error ("unconvertible operand %c %qs", code?code:'-', pattern);
3514       debug_rtx(x);
3515     }
3516
3517   return;
3518 }
3519
3520 void
3521 mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3522                         int noperands ATTRIBUTE_UNUSED)
3523 {
3524   /* Despite the fact that MeP is perfectly capable of branching and
3525      doing something else in the same bundle, gcc does jump
3526      optimization *after* scheduling, so we cannot trust the bundling
3527      flags on jump instructions.  */
3528   if (GET_MODE (insn) == BImode
3529       && get_attr_slots (insn) != SLOTS_CORE)
3530     fputc ('+', asm_out_file);
3531 }
3532
3533 /* Function args in registers.  */
3534
3535 static void
3536 mep_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
3537                             enum machine_mode mode ATTRIBUTE_UNUSED,
3538                             tree type ATTRIBUTE_UNUSED, int *pretend_size,
3539                             int second_time ATTRIBUTE_UNUSED)
3540 {
3541   int nsave = 4 - (cum->nregs + 1);
3542
3543   if (nsave > 0)
3544     cfun->machine->arg_regs_to_save = nsave;
3545   *pretend_size = nsave * 4;
3546 }
3547
3548 static int
3549 bytesize (const_tree type, enum machine_mode mode)
3550 {
3551   if (mode == BLKmode)
3552     return int_size_in_bytes (type);
3553   return GET_MODE_SIZE (mode);
3554 }
3555
3556 static rtx
3557 mep_expand_builtin_saveregs (void)
3558 {
3559   int bufsize, i, ns;
3560   rtx regbuf;
3561
3562   ns = cfun->machine->arg_regs_to_save;
3563   if (TARGET_IVC2)
3564     {
3565       bufsize = 8 * ((ns + 1) / 2) + 8 * ns;
3566       regbuf = assign_stack_local (SImode, bufsize, 64);
3567     }
3568   else
3569     {
3570       bufsize = ns * 4;
3571       regbuf = assign_stack_local (SImode, bufsize, 32);
3572     }
3573
3574   move_block_from_reg (5-ns, regbuf, ns);
3575
3576   if (TARGET_IVC2)
3577     {
3578       rtx tmp = gen_rtx_MEM (DImode, XEXP (regbuf, 0));
3579       int ofs = 8 * ((ns+1)/2);
3580
3581       for (i=0; i<ns; i++)
3582         {
3583           int rn = (4-ns) + i + 49;
3584           rtx ptr;
3585
3586           ptr = offset_address (tmp, GEN_INT (ofs), 2);
3587           emit_move_insn (ptr, gen_rtx_REG (DImode, rn));
3588           ofs += 8;
3589         }
3590     }
3591   return XEXP (regbuf, 0);
3592 }
3593
3594 #define VECTOR_TYPE_P(t) (TREE_CODE(t) == VECTOR_TYPE)
3595
3596 static tree
3597 mep_build_builtin_va_list (void)
3598 {
3599   tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3600   tree record;
3601
3602
3603   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
3604
3605   f_next_gp = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3606                           get_identifier ("__va_next_gp"), ptr_type_node);
3607   f_next_gp_limit = build_decl (BUILTINS_LOCATION, FIELD_DECL,
3608                                 get_identifier ("__va_next_gp_limit"),
3609                                 ptr_type_node);
3610   f_next_cop = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_cop"),
3611                            ptr_type_node);
3612   f_next_stack = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_stack"),
3613                              ptr_type_node);
3614
3615   DECL_FIELD_CONTEXT (f_next_gp) = record;
3616   DECL_FIELD_CONTEXT (f_next_gp_limit) = record;
3617   DECL_FIELD_CONTEXT (f_next_cop) = record;
3618   DECL_FIELD_CONTEXT (f_next_stack) = record;
3619
3620   TYPE_FIELDS (record) = f_next_gp;
3621   TREE_CHAIN (f_next_gp) = f_next_gp_limit;
3622   TREE_CHAIN (f_next_gp_limit) = f_next_cop;
3623   TREE_CHAIN (f_next_cop) = f_next_stack;
3624
3625   layout_type (record);
3626
3627   return record;
3628 }
3629
3630 static void
3631 mep_expand_va_start (tree valist, rtx nextarg)
3632 {
3633   tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3634   tree next_gp, next_gp_limit, next_cop, next_stack;
3635   tree t, u;
3636   int ns;
3637
3638   ns = cfun->machine->arg_regs_to_save;
3639
3640   f_next_gp = TYPE_FIELDS (va_list_type_node);
3641   f_next_gp_limit = TREE_CHAIN (f_next_gp);
3642   f_next_cop = TREE_CHAIN (f_next_gp_limit);
3643   f_next_stack = TREE_CHAIN (f_next_cop);
3644
3645   next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3646                     NULL_TREE);
3647   next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3648                           valist, f_next_gp_limit, NULL_TREE);
3649   next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3650                      NULL_TREE);
3651   next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3652                        valist, f_next_stack, NULL_TREE);
3653
3654   /* va_list.next_gp = expand_builtin_saveregs (); */
3655   u = make_tree (sizetype, expand_builtin_saveregs ());
3656   u = fold_convert (ptr_type_node, u);
3657   t = build2 (MODIFY_EXPR, ptr_type_node, next_gp, u);
3658   TREE_SIDE_EFFECTS (t) = 1;
3659   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3660
3661   /* va_list.next_gp_limit = va_list.next_gp + 4 * ns; */
3662   u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
3663                    size_int (4 * ns));
3664   t = build2 (MODIFY_EXPR, ptr_type_node, next_gp_limit, u);
3665   TREE_SIDE_EFFECTS (t) = 1;
3666   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3667
3668   u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
3669                    size_int (8 * ((ns+1)/2)));
3670   /* va_list.next_cop = ROUND_UP(va_list.next_gp_limit,8); */
3671   t = build2 (MODIFY_EXPR, ptr_type_node, next_cop, u);
3672   TREE_SIDE_EFFECTS (t) = 1;
3673   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3674
3675   /* va_list.next_stack = nextarg; */
3676   u = make_tree (ptr_type_node, nextarg);
3677   t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
3678   TREE_SIDE_EFFECTS (t) = 1;
3679   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3680 }
3681
3682 static tree
3683 mep_gimplify_va_arg_expr (tree valist, tree type,
3684                           tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
3685 {
3686   HOST_WIDE_INT size, rsize;
3687   bool by_reference, ivc2_vec;
3688   tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack;
3689   tree next_gp, next_gp_limit, next_cop, next_stack;
3690   tree label_sover, label_selse;
3691   tree tmp, res_addr;
3692
3693   ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type);
3694
3695   size = int_size_in_bytes (type);
3696   by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0);
3697
3698   if (by_reference)
3699     {
3700       type = build_pointer_type (type);
3701       size = 4;
3702     }
3703   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
3704
3705   f_next_gp = TYPE_FIELDS (va_list_type_node);
3706   f_next_gp_limit = TREE_CHAIN (f_next_gp);
3707   f_next_cop = TREE_CHAIN (f_next_gp_limit);
3708   f_next_stack = TREE_CHAIN (f_next_cop);
3709
3710   next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp,
3711                     NULL_TREE);
3712   next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit),
3713                           valist, f_next_gp_limit, NULL_TREE);
3714   next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop,
3715                      NULL_TREE);
3716   next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
3717                        valist, f_next_stack, NULL_TREE);
3718
3719   /* if f_next_gp < f_next_gp_limit
3720        IF (VECTOR_P && IVC2)
3721          val = *f_next_cop;
3722        ELSE
3723          val = *f_next_gp;
3724        f_next_gp += 4;
3725        f_next_cop += 8;
3726      else
3727        label_selse:
3728        val = *f_next_stack;
3729        f_next_stack += rsize;
3730      label_sover:
3731   */
3732
3733   label_sover = create_artificial_label (UNKNOWN_LOCATION);
3734   label_selse = create_artificial_label (UNKNOWN_LOCATION);
3735   res_addr = create_tmp_var (ptr_type_node, NULL);
3736
3737   tmp = build2 (GE_EXPR, boolean_type_node, next_gp,
3738                 unshare_expr (next_gp_limit));
3739   tmp = build3 (COND_EXPR, void_type_node, tmp,
3740                 build1 (GOTO_EXPR, void_type_node,
3741                         unshare_expr (label_selse)),
3742                 NULL_TREE);
3743   gimplify_and_add (tmp, pre_p);
3744
3745   if (ivc2_vec)
3746     {
3747       tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_cop);
3748       gimplify_and_add (tmp, pre_p);
3749     }
3750   else
3751     {
3752       tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_gp);
3753       gimplify_and_add (tmp, pre_p);
3754     }
3755
3756   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3757                 unshare_expr (next_gp), size_int (4));
3758   gimplify_assign (unshare_expr (next_gp), tmp, pre_p);
3759
3760   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3761                 unshare_expr (next_cop), size_int (8));
3762   gimplify_assign (unshare_expr (next_cop), tmp, pre_p);
3763
3764   tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (label_sover));
3765   gimplify_and_add (tmp, pre_p);
3766
3767   /* - - */
3768
3769   tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_selse));
3770   gimplify_and_add (tmp, pre_p);
3771
3772   tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, unshare_expr (next_stack));
3773   gimplify_and_add (tmp, pre_p);
3774
3775   tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
3776                 unshare_expr (next_stack), size_int (rsize));
3777   gimplify_assign (unshare_expr (next_stack), tmp, pre_p);
3778
3779   /* - - */
3780
3781   tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_sover));
3782   gimplify_and_add (tmp, pre_p);
3783
3784   res_addr = fold_convert (build_pointer_type (type), res_addr);
3785
3786   if (by_reference)
3787     res_addr = build_va_arg_indirect_ref (res_addr);
3788
3789   return build_va_arg_indirect_ref (res_addr);
3790 }
3791
3792 void
3793 mep_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
3794                           rtx libname ATTRIBUTE_UNUSED,
3795                           tree fndecl ATTRIBUTE_UNUSED)
3796 {
3797   pcum->nregs = 0;
3798
3799   if (fntype && lookup_attribute ("vliw", TYPE_ATTRIBUTES (fntype)))
3800     pcum->vliw = 1;
3801   else
3802     pcum->vliw = 0;
3803 }
3804
3805 rtx
3806 mep_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,
3807                   tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
3808 {
3809   /* VOIDmode is a signal for the backend to pass data to the call
3810      expander via the second operand to the call pattern.  We use
3811      this to determine whether to use "jsr" or "jsrv".  */
3812   if (mode == VOIDmode)
3813     return GEN_INT (cum.vliw);
3814
3815   /* If we havn't run out of argument registers, return the next.  */
3816   if (cum.nregs < 4)
3817     {
3818       if (type && TARGET_IVC2 && VECTOR_TYPE_P (type))
3819         return gen_rtx_REG (mode, cum.nregs + 49);
3820       else
3821         return gen_rtx_REG (mode, cum.nregs + 1);
3822     }
3823
3824   /* Otherwise the argument goes on the stack.  */
3825   return NULL_RTX;
3826 }
3827
3828 static bool
3829 mep_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
3830                        enum machine_mode mode,
3831                        const_tree        type,
3832                        bool              named ATTRIBUTE_UNUSED)
3833 {
3834   int size = bytesize (type, mode);
3835
3836   /* This is non-obvious, but yes, large values passed after we've run
3837      out of registers are *still* passed by reference - we put the
3838      address of the parameter on the stack, as well as putting the
3839      parameter itself elsewhere on the stack.  */
3840
3841   if (size <= 0 || size > 8)
3842     return true;
3843   if (size <= 4)
3844     return false;
3845   if (TARGET_IVC2 && cum->nregs < 4 && type != NULL_TREE && VECTOR_TYPE_P (type))
3846     return false;
3847   return true;
3848 }
3849
3850 void
3851 mep_arg_advance (CUMULATIVE_ARGS *pcum,
3852                  enum machine_mode mode ATTRIBUTE_UNUSED,
3853                  tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
3854 {
3855   pcum->nregs += 1;
3856 }
3857
3858 bool
3859 mep_return_in_memory (const_tree type, const_tree decl ATTRIBUTE_UNUSED)
3860 {
3861   int size = bytesize (type, BLKmode);
3862   if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3863     return size > 0 && size <= 8 ? 0 : 1;
3864   return size > 0 && size <= 4 ? 0 : 1;
3865 }
3866
3867 static bool
3868 mep_narrow_volatile_bitfield (void)
3869 {
3870   return true;
3871   return false;
3872 }
3873
3874 /* Implement FUNCTION_VALUE.  All values are returned in $0.  */
3875
3876 rtx
3877 mep_function_value (tree type, tree func ATTRIBUTE_UNUSED)
3878 {
3879   if (TARGET_IVC2 && VECTOR_TYPE_P (type))
3880     return gen_rtx_REG (TYPE_MODE (type), 48);
3881   return gen_rtx_REG (TYPE_MODE (type), RETURN_VALUE_REGNUM);
3882 }
3883
3884 /* Implement LIBCALL_VALUE, using the same rules as mep_function_value.  */
3885
3886 rtx
3887 mep_libcall_value (enum machine_mode mode)
3888 {
3889   return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
3890 }
3891
3892 /* Handle pipeline hazards.  */
3893
3894 typedef enum { op_none, op_stc, op_fsft, op_ret } op_num;
3895 static const char *opnames[] = { "", "stc", "fsft", "ret" };
3896
3897 static int prev_opcode = 0;
3898
3899 /* This isn't as optimal as it could be, because we don't know what
3900    control register the STC opcode is storing in.  We only need to add
3901    the nop if it's the relevent register, but we add it for irrelevent
3902    registers also.  */
3903
3904 void
3905 mep_asm_output_opcode (FILE *file, const char *ptr)
3906 {
3907   int this_opcode = op_none;
3908   const char *hazard = 0;
3909
3910   switch (*ptr)
3911     {
3912     case 'f':
3913       if (strncmp (ptr, "fsft", 4) == 0 && !ISGRAPH (ptr[4]))
3914         this_opcode = op_fsft;
3915       break;
3916     case 'r':
3917       if (strncmp (ptr, "ret", 3) == 0 && !ISGRAPH (ptr[3]))
3918         this_opcode = op_ret;
3919       break;
3920     case 's':
3921       if (strncmp (ptr, "stc", 3) == 0 && !ISGRAPH (ptr[3]))
3922         this_opcode = op_stc;
3923       break;
3924     }
3925
3926   if (prev_opcode == op_stc && this_opcode == op_fsft)
3927     hazard = "nop";
3928   if (prev_opcode == op_stc && this_opcode == op_ret)
3929     hazard = "nop";
3930
3931   if (hazard)
3932     fprintf(file, "%s\t# %s-%s hazard\n\t",
3933             hazard, opnames[prev_opcode], opnames[this_opcode]);
3934
3935   prev_opcode = this_opcode;
3936 }
3937
3938 /* Handle attributes.  */
3939
3940 static tree
3941 mep_validate_based_tiny (tree *node, tree name, tree args,
3942                          int flags ATTRIBUTE_UNUSED, bool *no_add)
3943 {
3944   if (TREE_CODE (*node) != VAR_DECL
3945       && TREE_CODE (*node) != POINTER_TYPE
3946       && TREE_CODE (*node) != TYPE_DECL)
3947     {
3948       warning (0, "%qE attribute only applies to variables", name);
3949       *no_add = true;
3950     }
3951   else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
3952     {
3953       if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
3954         {
3955           warning (0, "address region attributes not allowed with auto storage class");
3956           *no_add = true;
3957         }
3958       /* Ignore storage attribute of pointed to variable: char __far * x;  */
3959       if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
3960         {
3961           warning (0, "address region attributes on pointed-to types ignored");
3962           *no_add = true;
3963         }
3964     }
3965   
3966   return NULL_TREE;
3967 }
3968
3969 static int
3970 mep_multiple_address_regions (tree list, bool check_section_attr)
3971 {
3972   tree a;
3973   int count_sections = 0;
3974   int section_attr_count = 0;
3975
3976   for (a = list; a; a = TREE_CHAIN (a))
3977     {
3978       if (is_attribute_p ("based", TREE_PURPOSE (a))
3979           || is_attribute_p ("tiny", TREE_PURPOSE (a))
3980           || is_attribute_p ("near", TREE_PURPOSE (a))
3981           || is_attribute_p ("far", TREE_PURPOSE (a))
3982           || is_attribute_p ("io", TREE_PURPOSE (a)))
3983         count_sections ++;
3984       if (check_section_attr)
3985         section_attr_count += is_attribute_p ("section", TREE_PURPOSE (a));
3986     }
3987         
3988   if (check_section_attr)
3989     return section_attr_count;
3990   else
3991     return count_sections;
3992 }
3993
3994 #define MEP_ATTRIBUTES(decl) \
3995   (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
3996                 : DECL_ATTRIBUTES (decl) \
3997                   ? (DECL_ATTRIBUTES (decl)) \
3998                   : TYPE_ATTRIBUTES (TREE_TYPE (decl))
3999
4000 static tree
4001 mep_validate_near_far (tree *node, tree name, tree args,
4002                        int flags ATTRIBUTE_UNUSED, bool *no_add)
4003 {
4004   if (TREE_CODE (*node) != VAR_DECL
4005       && TREE_CODE (*node) != FUNCTION_DECL
4006       && TREE_CODE (*node) != METHOD_TYPE
4007       && TREE_CODE (*node) != POINTER_TYPE
4008       && TREE_CODE (*node) != TYPE_DECL)
4009     {
4010       warning (0, "%qE attribute only applies to variables and functions",
4011                name);
4012       *no_add = true;
4013     }
4014   else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
4015     {
4016       if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
4017         {
4018           warning (0, "address region attributes not allowed with auto storage class");
4019           *no_add = true;
4020         }
4021       /* Ignore storage attribute of pointed to variable: char __far * x;  */
4022       if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE)
4023         {
4024           warning (0, "address region attributes on pointed-to types ignored");
4025           *no_add = true;
4026         }
4027     }
4028   else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0)
4029     {
4030       warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d",
4031                name, DECL_NAME (*node), DECL_SOURCE_LINE (*node));
4032       DECL_ATTRIBUTES (*node) = NULL_TREE;
4033     }
4034   return NULL_TREE;
4035 }
4036
4037 static tree
4038 mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4039                            int flags ATTRIBUTE_UNUSED, bool *no_add)
4040 {
4041   if (TREE_CODE (*node) != FUNCTION_DECL
4042       && TREE_CODE (*node) != METHOD_TYPE)
4043     {
4044       warning (0, "%qE attribute only applies to functions", name);
4045       *no_add = true;
4046     }
4047   return NULL_TREE;
4048 }
4049
4050 static tree
4051 mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
4052                         int flags ATTRIBUTE_UNUSED, bool *no_add)
4053 {
4054   tree function_type;
4055
4056   if (TREE_CODE (*node) != FUNCTION_DECL)
4057     {
4058       warning (0, "%qE attribute only applies to functions", name);
4059       *no_add = true;
4060       return NULL_TREE;
4061     }
4062
4063   if (DECL_DECLARED_INLINE_P (*node))
4064     error ("cannot inline interrupt function %qE", DECL_NAME (*node));
4065   DECL_UNINLINABLE (*node) = 1;
4066
4067   function_type = TREE_TYPE (*node);
4068
4069   if (TREE_TYPE (function_type) != void_type_node)
4070     error ("interrupt function must have return type of void");
4071
4072   if (TYPE_ARG_TYPES (function_type)
4073       && (TREE_VALUE (TYPE_ARG_TYPES (function_type)) != void_type_node
4074           || TREE_CHAIN (TYPE_ARG_TYPES (function_type)) != NULL_TREE))
4075     error ("interrupt function must have no arguments");
4076
4077   return NULL_TREE;
4078 }
4079
4080 static tree
4081 mep_validate_io_cb (tree *node, tree name, tree args,
4082                     int flags ATTRIBUTE_UNUSED, bool *no_add)
4083 {
4084   if (TREE_CODE (*node) != VAR_DECL)
4085     {
4086       warning (0, "%qE attribute only applies to variables", name);
4087       *no_add = true;
4088     }
4089
4090   if (args != NULL_TREE)
4091     {
4092       if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
4093         TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
4094       if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
4095         {
4096           warning (0, "%qE attribute allows only an integer constant argument",
4097                    name);
4098           *no_add = true;
4099         }
4100     }
4101
4102   if (*no_add == false && !TARGET_IO_NO_VOLATILE)
4103     TREE_THIS_VOLATILE (*node) = 1;
4104
4105   return NULL_TREE;
4106 }
4107
4108 static tree
4109 mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED, 
4110                    int flags ATTRIBUTE_UNUSED, bool *no_add)
4111 {
4112   if (TREE_CODE (*node) != FUNCTION_TYPE
4113       && TREE_CODE (*node) != FUNCTION_DECL
4114       && TREE_CODE (*node) != METHOD_TYPE
4115       && TREE_CODE (*node) != FIELD_DECL
4116       && TREE_CODE (*node) != TYPE_DECL)
4117     {
4118       static int gave_pointer_note = 0;
4119       static int gave_array_note = 0;
4120       static const char * given_type = NULL;
4121  
4122       given_type = tree_code_name[TREE_CODE (*node)];
4123       if (TREE_CODE (*node) == POINTER_TYPE)
4124         given_type = "pointers";
4125       if (TREE_CODE (*node) == ARRAY_TYPE)
4126         given_type = "arrays";
4127  
4128       if (given_type)
4129         warning (0, "%qE attribute only applies to functions, not %s",
4130                  name, given_type);
4131       else
4132         warning (0, "%qE attribute only applies to functions",
4133                  name);
4134       *no_add = true;
4135  
4136       if (TREE_CODE (*node) == POINTER_TYPE
4137           && !gave_pointer_note)
4138         {
4139           inform (input_location, "To describe a pointer to a VLIW function, use syntax like this:");
4140           inform (input_location, "  typedef int (__vliw *vfuncptr) ();");
4141           gave_pointer_note = 1;
4142         }
4143  
4144       if (TREE_CODE (*node) == ARRAY_TYPE
4145           && !gave_array_note)
4146         {
4147           inform (input_location, "To describe an array of VLIW function pointers, use syntax like this:");
4148           inform (input_location, "  typedef int (__vliw *vfuncptr[]) ();");
4149           gave_array_note = 1;
4150         }
4151     }
4152   if (!TARGET_VLIW)
4153     error ("VLIW functions are not allowed without a VLIW configuration");
4154   return NULL_TREE;
4155 }
4156
4157 static const struct attribute_spec mep_attribute_table[11] =
4158 {
4159   /* name         min max decl   type   func   handler */
4160   { "based",        0, 0, false, false, false, mep_validate_based_tiny },
4161   { "tiny",         0, 0, false, false, false, mep_validate_based_tiny },
4162   { "near",         0, 0, false, false, false, mep_validate_near_far },
4163   { "far",          0, 0, false, false, false, mep_validate_near_far },
4164   { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt },
4165   { "interrupt",    0, 0, false, false, false, mep_validate_interrupt },
4166   { "io",           0, 1, false, false, false, mep_validate_io_cb },
4167   { "cb",           0, 1, false, false, false, mep_validate_io_cb },
4168   { "vliw",         0, 0, false, true,  false, mep_validate_vliw },
4169   { NULL,           0, 0, false, false, false, NULL }
4170 };
4171
4172 static bool
4173 mep_function_attribute_inlinable_p (const_tree callee)
4174 {
4175   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee));
4176   if (!attrs) attrs = DECL_ATTRIBUTES (callee);
4177   return (lookup_attribute ("disinterrupt", attrs) == 0
4178           && lookup_attribute ("interrupt", attrs) == 0);
4179 }
4180
4181 static bool
4182 mep_can_inline_p (tree caller, tree callee)
4183 {
4184   if (TREE_CODE (callee) == ADDR_EXPR)
4185     callee = TREE_OPERAND (callee, 0);
4186  
4187   if (!mep_vliw_function_p (caller)
4188       && mep_vliw_function_p (callee))
4189     {
4190       return false;
4191     }
4192   return true;
4193 }
4194
4195 #define FUNC_CALL               1
4196 #define FUNC_DISINTERRUPT       2
4197
4198
4199 struct GTY(()) pragma_entry {
4200   int used;
4201   int flag;
4202   const char *funcname;
4203 };
4204 typedef struct pragma_entry pragma_entry;
4205
4206 /* Hash table of farcall-tagged sections.  */
4207 static GTY((param_is (pragma_entry))) htab_t pragma_htab;
4208
4209 static int
4210 pragma_entry_eq (const void *p1, const void *p2)
4211 {
4212   const pragma_entry *old = (const pragma_entry *) p1;
4213   const char *new_name = (const char *) p2;
4214
4215   return strcmp (old->funcname, new_name) == 0;
4216 }
4217
4218 static hashval_t
4219 pragma_entry_hash (const void *p)
4220 {
4221   const pragma_entry *old = (const pragma_entry *) p;
4222   return htab_hash_string (old->funcname);
4223 }