OSDN Git Service

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