OSDN Git Service

PR c/42312
[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;
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   really_need_stack_frame = frame_size;
2871
2872   really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
2873
2874   sp_offset = reg_save_size;
2875   if (sp_offset + frame_size < 128)
2876     sp_offset += frame_size ;
2877
2878   add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1);
2879
2880   for (i=0; i<FIRST_PSEUDO_REGISTER; i++)
2881     if (mep_call_saves_register(i))
2882       {
2883         rtx mem;
2884         bool maybe_dead_p;
2885         enum machine_mode rmode;
2886
2887         rss = cfun->machine->reg_save_slot[i];
2888
2889         if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
2890             && (!mep_reg_set_in_function (i)
2891                 && !mep_interrupt_p ()))
2892           continue;
2893
2894         if (mep_reg_size (i) == 8)
2895           rmode = DImode;
2896         else
2897           rmode = SImode;
2898
2899         /* If there is a pseudo associated with this register's initial value,
2900            reload might have already spilt it to the stack slot suggested by
2901            ALLOCATE_INITIAL_VALUE.  The moves emitted here can then be safely
2902            deleted as dead.  */
2903         mem = gen_rtx_MEM (rmode,
2904                            plus_constant (stack_pointer_rtx, sp_offset - rss));
2905         maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i));
2906
2907         if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
2908           F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p));
2909         else if (rmode == DImode)
2910           {
2911             rtx insn;
2912             int be = TARGET_BIG_ENDIAN ? 4 : 0;
2913
2914             mem = gen_rtx_MEM (SImode,
2915                                plus_constant (stack_pointer_rtx, sp_offset - rss + be));
2916
2917             maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2918                              gen_rtx_REG (SImode, i),
2919                              maybe_dead_p);
2920             maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2921                              gen_rtx_ZERO_EXTRACT (SImode,
2922                                                    gen_rtx_REG (DImode, i),
2923                                                    GEN_INT (32),
2924                                                    GEN_INT (32)),
2925                              maybe_dead_p);
2926             insn = maybe_dead_move (mem,
2927                                     gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
2928                                     maybe_dead_p);
2929             RTX_FRAME_RELATED_P (insn) = 1;
2930             
2931             add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2932                           gen_rtx_SET (VOIDmode,
2933                                        copy_rtx (mem),
2934                                        gen_rtx_REG (rmode, i)));
2935             mem = gen_rtx_MEM (SImode,
2936                                plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be)));
2937             insn = maybe_dead_move (mem,
2938                                     gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1),
2939                                     maybe_dead_p);
2940           }
2941         else
2942           {
2943             rtx insn;
2944             maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2945                              gen_rtx_REG (rmode, i),
2946                              maybe_dead_p);
2947             insn = maybe_dead_move (mem,
2948                                     gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
2949                                     maybe_dead_p);
2950             RTX_FRAME_RELATED_P (insn) = 1;
2951             
2952             add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2953                           gen_rtx_SET (VOIDmode,
2954                                        copy_rtx (mem),
2955                                        gen_rtx_REG (rmode, i)));
2956           }
2957       }
2958   
2959   if (frame_pointer_needed)
2960     {
2961       /* We've already adjusted down by sp_offset.  Total $sp change
2962          is reg_save_size + frame_size.  We want a net change here of
2963          just reg_save_size.  */
2964       add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1);
2965     }
2966
2967   add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1);
2968
2969   if (mep_interrupt_p ())
2970     {
2971       mep_reload_pointer(GP_REGNO, "__sdabase");
2972       mep_reload_pointer(TP_REGNO, "__tpbase");
2973     }
2974 }
2975
2976 static void
2977 mep_start_function (FILE *file, HOST_WIDE_INT hwi_local)
2978 {
2979   int local = hwi_local;
2980   int frame_size = local + crtl->outgoing_args_size;
2981   int reg_save_size;
2982   int ffill;
2983   int i, sp, skip;
2984   int sp_offset;
2985   int slot_map[FIRST_PSEUDO_REGISTER], si, sj;
2986
2987   reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
2988   frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
2989   sp_offset = reg_save_size + frame_size;
2990
2991   ffill = cfun->machine->frame_filler;
2992
2993   if (cfun->machine->mep_frame_pointer_needed)
2994     reg_names[FP_REGNO] = "$fp";
2995   else
2996     reg_names[FP_REGNO] = "$8";
2997
2998   if (sp_offset == 0)
2999     return;
3000
3001   if (debug_info_level == DINFO_LEVEL_NONE)
3002     {
3003       fprintf (file, "\t# frame: %d", sp_offset);
3004       if (reg_save_size)
3005         fprintf (file, "   %d regs", reg_save_size);
3006       if (local)
3007         fprintf (file, "   %d locals", local);
3008       if (crtl->outgoing_args_size)
3009         fprintf (file, "   %d args", crtl->outgoing_args_size);
3010       fprintf (file, "\n");
3011       return;
3012     }
3013
3014   fprintf (file, "\t#\n");
3015   fprintf (file, "\t# Initial Frame Information:\n");
3016   if (sp_offset || !frame_pointer_needed)
3017     fprintf (file, "\t# Entry   ---------- 0\n");
3018
3019   /* Sort registers by save slots, so they're printed in the order
3020      they appear in memory, not the order they're saved in.  */
3021   for (si=0; si<FIRST_PSEUDO_REGISTER; si++)
3022     slot_map[si] = si;
3023   for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++)
3024     for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++)
3025       if (cfun->machine->reg_save_slot[slot_map[si]]
3026           > cfun->machine->reg_save_slot[slot_map[sj]])
3027         {
3028           int t = slot_map[si];
3029           slot_map[si] = slot_map[sj];
3030           slot_map[sj] = t;
3031         }
3032
3033   sp = 0;
3034   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3035     {
3036       int rsize;
3037       int r = slot_map[i];
3038       int rss = cfun->machine->reg_save_slot[r];
3039
3040       if (!mep_call_saves_register (r))
3041         continue;
3042
3043       if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO)
3044           && (!mep_reg_set_in_function (r)
3045               && !mep_interrupt_p ()))
3046         continue;
3047
3048       rsize = mep_reg_size(r);
3049       skip = rss - (sp+rsize);
3050       if (skip)
3051         fprintf (file, "\t#         %3d bytes for alignment\n", skip);
3052       fprintf (file, "\t#         %3d bytes for saved %-3s   %3d($sp)\n",
3053                rsize, reg_names[r], sp_offset - rss);
3054       sp = rss;
3055     }
3056
3057   skip = reg_save_size - sp;
3058   if (skip)
3059     fprintf (file, "\t#         %3d bytes for alignment\n", skip);
3060
3061   if (frame_pointer_needed)
3062     fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size);
3063   if (local)
3064     fprintf (file, "\t#         %3d bytes for local vars\n", local);
3065   if (ffill)
3066     fprintf (file, "\t#         %3d bytes for alignment\n", ffill);
3067   if (crtl->outgoing_args_size)
3068     fprintf (file, "\t#         %3d bytes for outgoing args\n",
3069              crtl->outgoing_args_size);
3070   fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset);
3071   fprintf (file, "\t#\n");
3072 }
3073
3074
3075 static int mep_prevent_lp_restore = 0;
3076 static int mep_sibcall_epilogue = 0;
3077
3078 void
3079 mep_expand_epilogue (void)
3080 {
3081   int i, sp_offset = 0;
3082   int reg_save_size = 0;
3083   int frame_size;
3084   int lp_temp = LP_REGNO, lp_slot = -1;
3085   int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size;
3086   int interrupt_handler = mep_interrupt_p ();
3087
3088   if (profile_arc_flag == 2)
3089     emit_insn (gen_mep_bb_trace_ret ());
3090
3091   reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM);
3092   frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM);
3093
3094   really_need_stack_frame |= mep_assign_save_slots (reg_save_size);
3095
3096   if (frame_pointer_needed)
3097     {
3098       /* If we have a frame pointer, we won't have a reliable stack
3099          pointer (alloca, you know), so rebase SP from FP */
3100       emit_move_insn (gen_rtx_REG (SImode, SP_REGNO),
3101                       gen_rtx_REG (SImode, FP_REGNO));
3102       sp_offset = reg_save_size;
3103     }
3104   else
3105     {
3106       /* SP is right under our local variable space.  Adjust it if
3107          needed.  */
3108       sp_offset = reg_save_size + frame_size;
3109       if (sp_offset >= 128)
3110         {
3111           add_constant (SP_REGNO, SP_REGNO, frame_size, 0);
3112           sp_offset -= frame_size;
3113         }
3114     }
3115
3116   /* This is backwards so that we restore the control and coprocessor
3117      registers before the temporary registers we use to restore
3118      them.  */
3119   for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--)
3120     if (mep_call_saves_register (i))
3121       {
3122         enum machine_mode rmode;
3123         int rss = cfun->machine->reg_save_slot[i];
3124
3125         if (mep_reg_size (i) == 8)
3126           rmode = DImode;
3127         else
3128           rmode = SImode;
3129
3130         if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO)
3131             && !(mep_reg_set_in_function (i) || interrupt_handler))
3132           continue;
3133         if (mep_prevent_lp_restore && i == LP_REGNO)
3134           continue;
3135         if (!mep_prevent_lp_restore
3136             && !interrupt_handler
3137             && (i == 10 || i == 11))
3138           continue;
3139   
3140         if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i))
3141           emit_move_insn (gen_rtx_REG (rmode, i),
3142                           gen_rtx_MEM (rmode,
3143                                        plus_constant (stack_pointer_rtx,
3144                                                       sp_offset-rss)));
3145         else
3146           {
3147             if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler)
3148               /* Defer this one so we can jump indirect rather than
3149                  copying the RA to $lp and "ret".  EH epilogues
3150                  automatically skip this anyway.  */
3151               lp_slot = sp_offset-rss;
3152             else
3153               {
3154                 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP),
3155                                 gen_rtx_MEM (rmode,
3156                                              plus_constant (stack_pointer_rtx,
3157                                                             sp_offset-rss)));
3158                 emit_move_insn (gen_rtx_REG (rmode, i),
3159                                 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP));
3160               }
3161           }
3162       }
3163   if (lp_slot != -1)
3164     {
3165       /* Restore this one last so we know it will be in the temp
3166          register when we return by jumping indirectly via the temp.  */
3167       emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP),
3168                       gen_rtx_MEM (SImode,
3169                                    plus_constant (stack_pointer_rtx,
3170                                                   lp_slot)));
3171       lp_temp = REGSAVE_CONTROL_TEMP;
3172     }
3173
3174
3175   add_constant (SP_REGNO, SP_REGNO, sp_offset, 0);
3176
3177   if (crtl->calls_eh_return && mep_prevent_lp_restore)
3178     emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO),
3179                            gen_rtx_REG (SImode, SP_REGNO),
3180                            cfun->machine->eh_stack_adjust));
3181
3182   if (mep_sibcall_epilogue)
3183     return;
3184
3185   if (mep_disinterrupt_p ())
3186     emit_insn (gen_mep_enable_int ());
3187
3188   if (mep_prevent_lp_restore)
3189     {
3190       emit_jump_insn (gen_eh_return_internal ());
3191       emit_barrier ();
3192     }
3193   else if (interrupt_handler)
3194     emit_jump_insn (gen_mep_reti ());
3195   else
3196     emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp)));
3197 }
3198
3199 void
3200 mep_expand_eh_return (rtx *operands)
3201 {
3202   if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO)
3203     {
3204       rtx ra = gen_rtx_REG (Pmode, LP_REGNO);
3205       emit_move_insn (ra, operands[0]);
3206       operands[0] = ra;
3207     }
3208
3209   emit_insn (gen_eh_epilogue (operands[0]));
3210 }
3211
3212 void
3213 mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED)
3214 {
3215   cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0);
3216   mep_prevent_lp_restore = 1;
3217   mep_expand_epilogue ();
3218   mep_prevent_lp_restore = 0;
3219 }
3220
3221 void
3222 mep_expand_sibcall_epilogue (void)
3223 {
3224   mep_sibcall_epilogue = 1;
3225   mep_expand_epilogue ();
3226   mep_sibcall_epilogue = 0;
3227 }
3228
3229 static bool
3230 mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
3231 {
3232   if (decl == NULL)
3233     return false;
3234
3235   if (mep_section_tag (DECL_RTL (decl)) == 'f')
3236     return false;
3237
3238   /* Can't call to a sibcall from an interrupt or disinterrupt function.  */
3239   if (mep_interrupt_p () || mep_disinterrupt_p ())
3240     return false;
3241
3242   return true;
3243 }
3244
3245 rtx
3246 mep_return_stackadj_rtx (void)
3247 {
3248   return gen_rtx_REG (SImode, 10);
3249 }
3250
3251 rtx
3252 mep_return_handler_rtx (void)
3253 {
3254   return gen_rtx_REG (SImode, LP_REGNO);
3255 }
3256
3257 void
3258 mep_function_profiler (FILE *file)
3259 {
3260   /* Always right at the beginning of the function.  */
3261   fprintf (file, "\t# mep function profiler\n");
3262   fprintf (file, "\tadd\t$sp, -8\n");
3263   fprintf (file, "\tsw\t$0, ($sp)\n");
3264   fprintf (file, "\tldc\t$0, $lp\n");
3265   fprintf (file, "\tsw\t$0, 4($sp)\n");
3266   fprintf (file, "\tbsr\t__mep_mcount\n");
3267   fprintf (file, "\tlw\t$0, 4($sp)\n");
3268   fprintf (file, "\tstc\t$0, $lp\n");
3269   fprintf (file, "\tlw\t$0, ($sp)\n");
3270   fprintf (file, "\tadd\t$sp, 8\n\n");
3271 }
3272
3273 const char *
3274 mep_emit_bb_trace_ret (void)
3275 {
3276   fprintf (asm_out_file, "\t# end of block profiling\n");
3277   fprintf (asm_out_file, "\tadd\t$sp, -8\n");
3278   fprintf (asm_out_file, "\tsw\t$0, ($sp)\n");
3279   fprintf (asm_out_file, "\tldc\t$0, $lp\n");
3280   fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n");
3281   fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n");
3282   fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n");
3283   fprintf (asm_out_file, "\tstc\t$0, $lp\n");
3284   fprintf (asm_out_file, "\tlw\t$0, ($sp)\n");
3285   fprintf (asm_out_file, "\tadd\t$sp, 8\n\n");
3286   return "";
3287 }
3288
3289 #undef SAVE
3290 #undef RESTORE
3291 \f
3292 /* Operand Printing.  */
3293
3294 void
3295 mep_print_operand_address (FILE *stream, rtx address)
3296 {
3297   if (GET_CODE (address) == MEM)
3298     address = XEXP (address, 0);
3299   else
3300     /* cf: gcc.dg/asm-4.c.  */
3301     gcc_assert (GET_CODE (address) == REG);
3302
3303   mep_print_operand (stream, address, 0);
3304 }
3305
3306 static struct
3307 {
3308   char code;
3309   const char *pattern;
3310   const char *format;
3311 }
3312 const conversions[] =
3313 {
3314   { 0, "r", "0" },
3315   { 0, "m+ri", "3(2)" },
3316   { 0, "mr", "(1)" },
3317   { 0, "ms", "(1)" },
3318   { 0, "ml", "(1)" },
3319   { 0, "mLrs", "%lo(3)(2)" },
3320   { 0, "mLr+si", "%lo(4+5)(2)" },
3321   { 0, "m+ru2s", "%tpoff(5)(2)" },
3322   { 0, "m+ru3s", "%sdaoff(5)(2)" },
3323   { 0, "m+r+u2si", "%tpoff(6+7)(2)" },
3324   { 0, "m+ru2+si", "%tpoff(6+7)(2)" },
3325   { 0, "m+r+u3si", "%sdaoff(6+7)(2)" },
3326   { 0, "m+ru3+si", "%sdaoff(6+7)(2)" },
3327   { 0, "mi", "(1)" },
3328   { 0, "m+si", "(2+3)" },
3329   { 0, "m+li", "(2+3)" },
3330   { 0, "i", "0" },
3331   { 0, "s", "0" },
3332   { 0, "+si", "1+2" },
3333   { 0, "+u2si", "%tpoff(3+4)" },
3334   { 0, "+u3si", "%sdaoff(3+4)" },
3335   { 0, "l", "0" },
3336   { 'b', "i", "0" },
3337   { 'B', "i", "0" },
3338   { 'U', "i", "0" },
3339   { 'h', "i", "0" },
3340   { 'h', "Hs", "%hi(1)" },
3341   { 'I', "i", "0" },
3342   { 'I', "u2s", "%tpoff(2)" },
3343   { 'I', "u3s", "%sdaoff(2)" },
3344   { 'I', "+u2si", "%tpoff(3+4)" },
3345   { 'I', "+u3si", "%sdaoff(3+4)" },
3346   { 'J', "i", "0" },
3347   { 'P', "mr", "(1\\+),\\0" },
3348   { 'x', "i", "0" },
3349   { 0, 0, 0 }
3350 };
3351
3352 static int
3353 unique_bit_in (HOST_WIDE_INT i)
3354 {
3355   switch (i & 0xff)
3356     {
3357     case 0x01: case 0xfe: return 0;
3358     case 0x02: case 0xfd: return 1;
3359     case 0x04: case 0xfb: return 2;
3360     case 0x08: case 0xf7: return 3;
3361     case 0x10: case 0x7f: return 4;
3362     case 0x20: case 0xbf: return 5;
3363     case 0x40: case 0xdf: return 6;
3364     case 0x80: case 0xef: return 7;
3365     default:
3366       gcc_unreachable ();
3367     }
3368 }
3369
3370 static int
3371 bit_size_for_clip (HOST_WIDE_INT i)
3372 {
3373   int rv;
3374
3375   for (rv = 0; rv < 31; rv ++)
3376     if (((HOST_WIDE_INT) 1 << rv) > i)
3377       return rv + 1;
3378   gcc_unreachable ();
3379 }
3380
3381 /* Print an operand to a assembler instruction.  */
3382
3383 void
3384 mep_print_operand (FILE *file, rtx x, int code)
3385 {
3386   int i, j;
3387   const char *real_name;
3388
3389   if (code == '<')
3390     {
3391       /* Print a mnemonic to do CR <- CR moves.  Find out which intrinsic
3392          we're using, then skip over the "mep_" part of its name.  */
3393       const struct cgen_insn *insn;
3394
3395       if (mep_get_move_insn (mep_cmov, &insn))
3396         fputs (cgen_intrinsics[insn->intrinsic] + 4, file);
3397       else
3398         mep_intrinsic_unavailable (mep_cmov);
3399       return;
3400     }
3401   if (code == 'L')
3402     {
3403       switch (GET_CODE (x))
3404         {
3405         case AND:
3406           fputs ("clr", file);
3407           return;
3408         case IOR:
3409           fputs ("set", file);
3410           return;
3411         case XOR:
3412           fputs ("not", file);
3413           return;
3414         default:
3415           output_operand_lossage ("invalid %%L code");
3416         }
3417     }
3418   if (code == 'M')
3419     {
3420       /* Print the second operand of a CR <- CR move.  If we're using
3421          a two-operand instruction (i.e., a real cmov), then just print
3422          the operand normally.  If we're using a "reg, reg, immediate"
3423          instruction such as caddi3, print the operand followed by a
3424          zero field.  If we're using a three-register instruction,
3425          print the operand twice.  */
3426       const struct cgen_insn *insn;
3427
3428       mep_print_operand (file, x, 0);
3429       if (mep_get_move_insn (mep_cmov, &insn)
3430           && insn_data[insn->icode].n_operands == 3)
3431         {
3432           fputs (", ", file);
3433           if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode))
3434             mep_print_operand (file, x, 0);
3435           else
3436             mep_print_operand (file, const0_rtx, 0);
3437         }
3438       return;
3439     }
3440
3441   encode_pattern (x);
3442   for (i = 0; conversions[i].pattern; i++)
3443     if (conversions[i].code == code
3444         && strcmp(conversions[i].pattern, pattern) == 0)
3445       {
3446         for (j = 0; conversions[i].format[j]; j++)
3447           if (conversions[i].format[j] == '\\')
3448             {
3449               fputc (conversions[i].format[j+1], file);
3450               j++;
3451             }
3452           else if (ISDIGIT(conversions[i].format[j]))
3453             {
3454               rtx r = patternr[conversions[i].format[j] - '0'];
3455               switch (GET_CODE (r))
3456                 {
3457                 case REG:
3458                   fprintf (file, "%s", reg_names [REGNO (r)]);
3459                   break;
3460                 case CONST_INT:
3461                   switch (code)
3462                     {
3463                     case 'b':
3464                       fprintf (file, "%d", unique_bit_in (INTVAL (r)));
3465                       break;
3466                     case 'B':
3467                       fprintf (file, "%d", bit_size_for_clip (INTVAL (r)));
3468                       break;
3469                     case 'h':
3470                       fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff);
3471                       break;
3472                     case 'U':
3473                       fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1);
3474                       break;
3475                     case 'J':
3476                       fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff);
3477                       break;
3478                     case 'x':
3479                       if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3480                           && !(INTVAL (r) & 0xff))
3481                         fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r));
3482                       else
3483                         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3484                       break;
3485                     case 'I':
3486                       if (INTVAL (r) & ~(HOST_WIDE_INT)0xff
3487                           && conversions[i].format[j+1] == 0)
3488                         {
3489                           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r));
3490                           fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff);
3491                         }
3492                       else
3493                         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3494                       break;
3495                     default:
3496                       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r));
3497                       break;
3498                     }
3499                   break;
3500                 case CONST_DOUBLE:
3501                   fprintf(file, "[const_double 0x%lx]",
3502                           (unsigned long) CONST_DOUBLE_HIGH(r));
3503                   break;
3504                 case SYMBOL_REF:
3505                   real_name = TARGET_STRIP_NAME_ENCODING (XSTR (r, 0));
3506                   assemble_name (file, real_name);
3507                   break;
3508                 case LABEL_REF:
3509                   output_asm_label (r);
3510                   break;
3511                 default:
3512                   fprintf (stderr, "don't know how to print this operand:");
3513                   debug_rtx (r);
3514                   gcc_unreachable ();
3515                 }
3516             }
3517           else
3518             {
3519               if (conversions[i].format[j] == '+'
3520                   && (!code || code == 'I')
3521                   && ISDIGIT (conversions[i].format[j+1])
3522                   && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT
3523                   && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0)
3524                 continue;
3525               fputc(conversions[i].format[j], file);
3526             }
3527         break;
3528       }
3529   if (!conversions[i].pattern)
3530     {
3531       error ("unconvertible operand %c %qs", code?code:'-', pattern);
3532       debug_rtx(x);
3533     }
3534
3535   return;
3536 }
3537
3538 void
3539 mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED,
3540                         int noperands ATTRIBUTE_UNUSED)
3541 {
3542   /* Despite the fact that MeP is perfectly capable of branching and
3543      doing something else in the same bundle, gcc does jump
3544      optimization *after* scheduling, so we cannot trust the bundling
3545      flags on jump instructions.  */
3546   if (GET_MODE (insn) == BImode
3547       && get_attr_slots (insn) != SLOTS_CORE)
3548     fputc ('+', asm_out_file);
3549 }
3550
3551 /* Function args in registers.  */
3552
3553 static void
3554 mep_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
3555                             enum machine_mode mode ATTRIBUTE_UNUSED,
3556                             tree type ATTRIBUTE_UNUSED, int *pretend_size,
3557                             int second_time ATTRIBUTE_UNUSED)
3558 {
3559   int nsave = 4 - (cum->nregs + 1);
3560
3561   if (nsave > 0)
3562     cfun->machine->arg_regs_to_save = nsave;
3563   *pretend_size = nsave * 4;
3564 }
3565
3566 static int
3567 bytesize (const_tree type, enum machine_mode mode)
3568 {
3569   if (mode == BLKmode)
3570     return int_size_in_bytes (type);
3571   return GET_MODE_SIZE (mode);
3572 }
3573
3574 static rtx
3575 mep_expand_builtin_saveregs (void)
3576 {
3577   int bufsize, i, ns;
3578   rtx regbuf;
3579
3580   ns = cfun->machine->arg_regs_to_save;
3581   if (TARGET_IVC2)
3582     {
3583 &nbs