xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/rl78/rl78.c (revision 16dce51364ebe8aeafbae46bc5aa167b8115bc45)
1 /* Subroutines used for code generation on Renesas RL78 processors.
2    Copyright (C) 2011-2015 Free Software Foundation, Inc.
3    Contributed by Red Hat.
4 
5    This file is part of GCC.
6 
7    GCC is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    GCC is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING3.  If not see
19    <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "hash-set.h"
26 #include "machmode.h"
27 #include "vec.h"
28 #include "double-int.h"
29 #include "input.h"
30 #include "alias.h"
31 #include "symtab.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "varasm.h"
37 #include "stor-layout.h"
38 #include "calls.h"
39 #include "rtl.h"
40 #include "regs.h"
41 #include "hard-reg-set.h"
42 #include "insn-config.h"
43 #include "conditions.h"
44 #include "output.h"
45 #include "insn-attr.h"
46 #include "flags.h"
47 #include "function.h"
48 #include "hashtab.h"
49 #include "statistics.h"
50 #include "real.h"
51 #include "fixed-value.h"
52 #include "expmed.h"
53 #include "dojump.h"
54 #include "explow.h"
55 #include "emit-rtl.h"
56 #include "stmt.h"
57 #include "expr.h"
58 #include "insn-codes.h"
59 #include "optabs.h"
60 #include "libfuncs.h"
61 #include "recog.h"
62 #include "diagnostic-core.h"
63 #include "toplev.h"
64 #include "reload.h"
65 #include "dominance.h"
66 #include "cfg.h"
67 #include "cfgrtl.h"
68 #include "cfganal.h"
69 #include "lcm.h"
70 #include "cfgbuild.h"
71 #include "cfgcleanup.h"
72 #include "predict.h"
73 #include "basic-block.h"
74 #include "df.h"
75 #include "ggc.h"
76 #include "tm_p.h"
77 #include "debug.h"
78 #include "target.h"
79 #include "target-def.h"
80 #include "langhooks.h"
81 #include "rl78-protos.h"
82 #include "dumpfile.h"
83 #include "tree-pass.h"
84 #include "context.h"
85 #include "tm-constrs.h" /* for satisfies_constraint_*().  */
86 #include "insn-flags.h" /* for gen_*().  */
87 #include "builtins.h"
88 #include "stringpool.h"
89 
90 static inline bool is_interrupt_func (const_tree decl);
91 static inline bool is_brk_interrupt_func (const_tree decl);
92 static void rl78_reorg (void);
93 static const char *rl78_strip_name_encoding (const char *);
94 static const char *rl78_strip_nonasm_name_encoding (const char *);
95 static section * rl78_select_section (tree, int, unsigned HOST_WIDE_INT);
96 
97 
98 /* Debugging statements are tagged with DEBUG0 only so that they can
99    be easily enabled individually, by replacing the '0' with '1' as
100    needed.  */
101 #define DEBUG0 0
102 #define DEBUG1 1
103 
104 /* REGISTER_NAMES has the names for individual 8-bit registers, but
105    these have the names we need to use when referring to 16-bit
106    register pairs.  */
107 static const char * const word_regnames[] =
108 {
109   "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
110   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
111   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
112   "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
113   "sp", "ap", "psw", "es", "cs"
114 };
115 
116 struct GTY(()) machine_function
117 {
118   /* If set, the rest of the fields have been computed.  */
119   int computed;
120   /* Which register pairs need to be pushed in the prologue.  */
121   int need_to_push [FIRST_PSEUDO_REGISTER / 2];
122 
123   /* These fields describe the frame layout...  */
124   /* arg pointer */
125   /* 4 bytes for saved PC */
126   int framesize_regs;
127   /* frame pointer */
128   int framesize_locals;
129   int framesize_outgoing;
130   /* stack pointer */
131   int framesize;
132 
133   /* If set, recog is allowed to match against the "real" patterns.  */
134   int real_insns_ok;
135   /* If set, recog is allowed to match against the "virtual" patterns.  */
136   int virt_insns_ok;
137   /* Set if the current function needs to clean up any trampolines.  */
138   int trampolines_used;
139   /* True if the ES register is used and hence
140      needs to be saved inside interrupt handlers.  */
141   bool uses_es;
142 };
143 
144 /* This is our init_machine_status, as set in
145    rl78_option_override.  */
146 static struct machine_function *
147 rl78_init_machine_status (void)
148 {
149   struct machine_function *m;
150 
151   m = ggc_cleared_alloc<machine_function> ();
152   m->virt_insns_ok = 1;
153 
154   return m;
155 }
156 
157 /* This pass converts virtual instructions using virtual registers, to
158    real instructions using real registers.  Rather than run it as
159    reorg, we reschedule it before vartrack to help with debugging.  */
160 namespace
161 {
162   const pass_data pass_data_rl78_devirt =
163     {
164       RTL_PASS, /* type */
165       "devirt", /* name */
166       OPTGROUP_NONE, /* optinfo_flags */
167       TV_MACH_DEP, /* tv_id */
168       0, /* properties_required */
169       0, /* properties_provided */
170       0, /* properties_destroyed */
171       0, /* todo_flags_start */
172       0, /* todo_flags_finish */
173     };
174 
175   class pass_rl78_devirt : public rtl_opt_pass
176   {
177   public:
178     pass_rl78_devirt (gcc::context *ctxt)
179       : rtl_opt_pass (pass_data_rl78_devirt, ctxt)
180       {
181       }
182 
183     /* opt_pass methods: */
184     virtual unsigned int execute (function *)
185     {
186       rl78_reorg ();
187       return 0;
188     }
189   };
190 } // anon namespace
191 
192 rtl_opt_pass *
193 make_pass_rl78_devirt (gcc::context *ctxt)
194 {
195   return new pass_rl78_devirt (ctxt);
196 }
197 
198 /* Redundant move elimination pass.  Must be run after the basic block
199    reordering pass for the best effect.  */
200 
201 static unsigned int
202 move_elim_pass (void)
203 {
204   rtx_insn *insn, *ninsn;
205   rtx prev = NULL_RTX;
206 
207   for (insn = get_insns (); insn; insn = ninsn)
208     {
209       rtx set;
210 
211       ninsn = next_nonnote_nondebug_insn (insn);
212 
213       if ((set = single_set (insn)) == NULL_RTX)
214 	{
215 	  prev = NULL_RTX;
216 	  continue;
217 	}
218 
219       /* If we have two SET insns in a row (without anything
220 	 between them) and the source of the second one is the
221 	 destination of the first one, and vice versa, then we
222 	 can eliminate the second SET.  */
223       if (prev
224 	  && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
225 	  && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
226 	  /* ... and none of the operands are volatile.  */
227 	  && ! volatile_refs_p (SET_SRC (prev))
228 	  && ! volatile_refs_p (SET_DEST (prev))
229 	  && ! volatile_refs_p (SET_SRC (set))
230 	  && ! volatile_refs_p (SET_DEST (set)))
231 	{
232 	  if (dump_file)
233 	    fprintf (dump_file, " Delete insn %d because it is redundant\n",
234 		     INSN_UID (insn));
235 
236 	  delete_insn (insn);
237 	  prev = NULL_RTX;
238 	}
239       else
240 	prev = set;
241     }
242 
243   if (dump_file)
244     print_rtl_with_bb (dump_file, get_insns (), 0);
245 
246   return 0;
247 }
248 
249 namespace
250 {
251   const pass_data pass_data_rl78_move_elim =
252     {
253       RTL_PASS, /* type */
254       "move_elim", /* name */
255       OPTGROUP_NONE, /* optinfo_flags */
256       TV_MACH_DEP, /* tv_id */
257       0, /* properties_required */
258       0, /* properties_provided */
259       0, /* properties_destroyed */
260       0, /* todo_flags_start */
261       0, /* todo_flags_finish */
262     };
263 
264   class pass_rl78_move_elim : public rtl_opt_pass
265   {
266   public:
267     pass_rl78_move_elim (gcc::context *ctxt)
268       : rtl_opt_pass (pass_data_rl78_move_elim, ctxt)
269       {
270       }
271 
272     /* opt_pass methods: */
273     virtual unsigned int execute (function *) { return move_elim_pass (); }
274   };
275 } // anon namespace
276 
277 rtl_opt_pass *
278 make_pass_rl78_move_elim (gcc::context *ctxt)
279 {
280   return new pass_rl78_move_elim (ctxt);
281 }
282 
283 #undef  TARGET_ASM_FILE_START
284 #define TARGET_ASM_FILE_START rl78_asm_file_start
285 
286 static void
287 rl78_asm_file_start (void)
288 {
289   int i;
290 
291   if (TARGET_G10)
292     {
293       /* The memory used is 0xffec8 to 0xffedf; real registers are in
294 	 0xffee0 to 0xffee7.  */
295       for (i = 8; i < 32; i++)
296 	fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
297     }
298   else
299     {
300       for (i = 0; i < 8; i++)
301 	{
302 	  fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
303 	  fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
304 	  fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
305 	}
306     }
307 
308   opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
309   struct register_pass_info rl78_devirt_info =
310     {
311       rl78_devirt_pass,
312       "pro_and_epilogue",
313       1,
314       PASS_POS_INSERT_BEFORE
315     };
316 
317   opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
318   struct register_pass_info rl78_move_elim_info =
319     {
320       rl78_move_elim_pass,
321       "bbro",
322       1,
323       PASS_POS_INSERT_AFTER
324     };
325 
326   register_pass (& rl78_devirt_info);
327   register_pass (& rl78_move_elim_info);
328 }
329 
330 void
331 rl78_output_symbol_ref (FILE * file, rtx sym)
332 {
333   tree type = SYMBOL_REF_DECL (sym);
334   const char *str = XSTR (sym, 0);
335 
336   if (str[0] == '*')
337     {
338       fputs (str + 1, file);
339     }
340   else
341     {
342       str = rl78_strip_nonasm_name_encoding (str);
343       if (type && TREE_CODE (type) == FUNCTION_DECL)
344 	{
345 	  fprintf (file, "%%code(");
346 	  assemble_name (file, str);
347 	  fprintf (file, ")");
348 	}
349       else
350 	assemble_name (file, str);
351     }
352 }
353 
354 #undef  TARGET_OPTION_OVERRIDE
355 #define TARGET_OPTION_OVERRIDE		rl78_option_override
356 
357 static void
358 rl78_option_override (void)
359 {
360   flag_omit_frame_pointer = 1;
361   flag_no_function_cse = 1;
362   flag_split_wide_types = 0;
363 
364   init_machine_status = rl78_init_machine_status;
365 
366   if (TARGET_ALLREGS)
367     {
368       int i;
369 
370       for (i = 24; i < 32; i++)
371 	fixed_regs[i] = 0;
372     }
373 
374   if (TARGET_ES0
375       && strcmp (lang_hooks.name, "GNU C")
376       /* Compiling with -flto results in a language of GNU GIMPLE being used... */
377       && strcmp (lang_hooks.name, "GNU GIMPLE"))
378     /* Address spaces are currently only supported by C.  */
379     error ("-mes0 can only be used with C");
380 }
381 
382 /* Most registers are 8 bits.  Some are 16 bits because, for example,
383    gcc doesn't like dealing with $FP as a register pair (the second
384    half of $fp is also 2 to keep reload happy wrt register pairs, but
385    no register class includes it).  This table maps register numbers
386    to size in bytes.  */
387 static const int register_sizes[] =
388 {
389   1, 1, 1, 1, 1, 1, 1, 1,
390   1, 1, 1, 1, 1, 1, 1, 1,
391   1, 1, 1, 1, 1, 1, 2, 2,
392   1, 1, 1, 1, 1, 1, 1, 1,
393   2, 2, 1, 1, 1
394 };
395 
396 /* Predicates used in the MD patterns.  This one is true when virtual
397    insns may be matched, which typically means before (or during) the
398    devirt pass.  */
399 bool
400 rl78_virt_insns_ok (void)
401 {
402   if (cfun)
403     return cfun->machine->virt_insns_ok;
404   return true;
405 }
406 
407 /* Predicates used in the MD patterns.  This one is true when real
408    insns may be matched, which typically means after (or during) the
409    devirt pass.  */
410 bool
411 rl78_real_insns_ok (void)
412 {
413   if (cfun)
414     return cfun->machine->real_insns_ok;
415   return false;
416 }
417 
418 /* Implements HARD_REGNO_NREGS.  */
419 int
420 rl78_hard_regno_nregs (int regno, machine_mode mode)
421 {
422   int rs = register_sizes[regno];
423   if (rs < 1)
424     rs = 1;
425   return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
426 }
427 
428 /* Implements HARD_REGNO_MODE_OK.  */
429 int
430 rl78_hard_regno_mode_ok (int regno, machine_mode mode)
431 {
432   int s = GET_MODE_SIZE (mode);
433 
434   if (s < 1)
435     return 0;
436   /* These are not to be used by gcc.  */
437   if (regno == 23 || regno == ES_REG || regno == CS_REG)
438     return 0;
439   /* $fp can always be accessed as a 16-bit value.  */
440   if (regno == FP_REG && s == 2)
441     return 1;
442   if (regno < SP_REG)
443     {
444       /* Since a reg-reg move is really a reg-mem move, we must
445 	 enforce alignment.  */
446       if (s > 1 && (regno % 2))
447 	return 0;
448       return 1;
449     }
450   if (s == CC_REGNUM)
451     return (mode == BImode);
452   /* All other registers must be accessed in their natural sizes.  */
453   if (s == register_sizes [regno])
454     return 1;
455   return 0;
456 }
457 
458 /* Simplify_gen_subreg() doesn't handle memory references the way we
459    need it to below, so we use this function for when we must get a
460    valid subreg in a "natural" state.  */
461 static rtx
462 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
463 {
464   if (GET_CODE (r) == MEM)
465     return adjust_address (r, mode, byte);
466   else
467     return simplify_gen_subreg (mode, r, omode, byte);
468 }
469 
470 /* Used by movsi.  Split SImode moves into two HImode moves, using
471    appropriate patterns for the upper and lower halves of symbols.  */
472 void
473 rl78_expand_movsi (rtx *operands)
474 {
475   rtx op00, op02, op10, op12;
476 
477   op00 = rl78_subreg (HImode, operands[0], SImode, 0);
478   op02 = rl78_subreg (HImode, operands[0], SImode, 2);
479   if (GET_CODE (operands[1]) == CONST
480       || GET_CODE (operands[1]) == SYMBOL_REF)
481     {
482       op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
483       op10 = gen_rtx_CONST (HImode, op10);
484       op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
485       op12 = gen_rtx_CONST (HImode, op12);
486     }
487   else
488     {
489       op10 = rl78_subreg (HImode, operands[1], SImode, 0);
490       op12 = rl78_subreg (HImode, operands[1], SImode, 2);
491     }
492 
493   if (rtx_equal_p (operands[0], operands[1]))
494     ;
495   else if (rtx_equal_p (op00, op12))
496     {
497       emit_move_insn (op02, op12);
498       emit_move_insn (op00, op10);
499     }
500   else
501     {
502       emit_move_insn (op00, op10);
503       emit_move_insn (op02, op12);
504     }
505 }
506 
507 /* Generate code to move an SImode value.  */
508 void
509 rl78_split_movsi (rtx *operands, enum machine_mode omode)
510 {
511   rtx op00, op02, op10, op12;
512 
513   op00 = rl78_subreg (HImode, operands[0], omode, 0);
514   op02 = rl78_subreg (HImode, operands[0], omode, 2);
515 
516   if (GET_CODE (operands[1]) == CONST
517       || GET_CODE (operands[1]) == SYMBOL_REF)
518     {
519       op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
520       op10 = gen_rtx_CONST (HImode, op10);
521       op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
522       op12 = gen_rtx_CONST (HImode, op12);
523     }
524   else
525     {
526       op10 = rl78_subreg (HImode, operands[1], omode, 0);
527       op12 = rl78_subreg (HImode, operands[1], omode, 2);
528     }
529 
530   if (rtx_equal_p (operands[0], operands[1]))
531     ;
532   else if (rtx_equal_p (op00, op12))
533     {
534       operands[2] = op02;
535       operands[4] = op12;
536       operands[3] = op00;
537       operands[5] = op10;
538     }
539   else
540     {
541       operands[2] = op00;
542       operands[4] = op10;
543       operands[3] = op02;
544       operands[5] = op12;
545     }
546 }
547 
548 /* Used by various two-operand expanders which cannot accept all
549    operands in the "far" namespace.  Force some such operands into
550    registers so that each pattern has at most one far operand.  */
551 int
552 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
553 {
554   int did = 0;
555   rtx temp_reg = NULL;
556 
557   /* FIXME: in the future, be smarter about only doing this if the
558      other operand is also far, assuming the devirtualizer can also
559      handle that.  */
560   if (rl78_far_p (operands[0]))
561     {
562       temp_reg = operands[0];
563       operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
564       did = 1;
565     }
566   if (!did)
567     return 0;
568 
569   emit_insn (gen (operands[0], operands[1]));
570   if (temp_reg)
571     emit_move_insn (temp_reg, operands[0]);
572   return 1;
573 }
574 
575 /* Likewise, but for three-operand expanders.  */
576 int
577 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
578 {
579   int did = 0;
580   rtx temp_reg = NULL;
581 
582   /* As an exception, we allow two far operands if they're identical
583      and the third operand is not a MEM.  This allows global variables
584      to be incremented, for example.  */
585   if (rtx_equal_p (operands[0], operands[1])
586       && ! MEM_P (operands[2]))
587     return 0;
588 
589   /* FIXME: Likewise.  */
590   if (rl78_far_p (operands[1]))
591     {
592       rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
593       emit_move_insn (temp_reg, operands[1]);
594       operands[1] = temp_reg;
595       did = 1;
596     }
597   if (rl78_far_p (operands[0]))
598     {
599       temp_reg = operands[0];
600       operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
601       did = 1;
602     }
603   if (!did)
604     return 0;
605 
606   emit_insn (gen (operands[0], operands[1], operands[2]));
607   if (temp_reg)
608     emit_move_insn (temp_reg, operands[0]);
609   return 1;
610 }
611 
612 #undef  TARGET_CAN_ELIMINATE
613 #define TARGET_CAN_ELIMINATE		rl78_can_eliminate
614 
615 static bool
616 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
617 {
618   return true;
619 }
620 
621 /* Returns true if the given register needs to be saved by the
622    current function.  */
623 static bool
624 need_to_save (unsigned int regno)
625 {
626   if (is_interrupt_func (cfun->decl))
627     {
628       /* We don't know what devirt will need */
629       if (regno < 8)
630 	return true;
631 
632        /* We don't need to save registers that have
633 	  been reserved for interrupt handlers.  */
634       if (regno > 23)
635 	return false;
636 
637       /* If the handler is a non-leaf function then it may call
638 	 non-interrupt aware routines which will happily clobber
639 	 any call_used registers, so we have to preserve them.  */
640       if (!crtl->is_leaf && call_used_regs[regno])
641 	return true;
642 
643       /* Otherwise we only have to save a register, call_used
644 	 or not, if it is used by this handler.  */
645       return df_regs_ever_live_p (regno);
646     }
647 
648   if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
649     return true;
650   if (fixed_regs[regno])
651     return false;
652   if (crtl->calls_eh_return)
653     return true;
654   if (df_regs_ever_live_p (regno)
655       && !call_used_regs[regno])
656     return true;
657   return false;
658 }
659 
660 /* We use this to wrap all emitted insns in the prologue.  */
661 static rtx
662 F (rtx x)
663 {
664   RTX_FRAME_RELATED_P (x) = 1;
665   return x;
666 }
667 
668 /* Compute all the frame-related fields in our machine_function
669    structure.  */
670 static void
671 rl78_compute_frame_info (void)
672 {
673   int i;
674 
675   cfun->machine->computed = 1;
676   cfun->machine->framesize_regs = 0;
677   cfun->machine->framesize_locals = get_frame_size ();
678   cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
679 
680   for (i = 0; i < 16; i ++)
681     if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
682       {
683 	cfun->machine->need_to_push [i] = 1;
684 	cfun->machine->framesize_regs += 2;
685       }
686     else
687       cfun->machine->need_to_push [i] = 0;
688 
689   if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
690     cfun->machine->framesize_locals ++;
691 
692   cfun->machine->framesize = (cfun->machine->framesize_regs
693 			      + cfun->machine->framesize_locals
694 			      + cfun->machine->framesize_outgoing);
695 }
696 
697 /* Returns true if the provided function has the specified attribute.  */
698 static inline bool
699 has_func_attr (const_tree decl, const char * func_attr)
700 {
701   if (decl == NULL_TREE)
702     decl = current_function_decl;
703 
704   return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
705 }
706 
707 /* Returns true if the provided function has the "interrupt" attribute.  */
708 static inline bool
709 is_interrupt_func (const_tree decl)
710 {
711   return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
712 }
713 
714 /* Returns true if the provided function has the "brk_interrupt" attribute.  */
715 static inline bool
716 is_brk_interrupt_func (const_tree decl)
717 {
718   return has_func_attr (decl, "brk_interrupt");
719 }
720 
721 /* Check "interrupt" attributes.  */
722 static tree
723 rl78_handle_func_attribute (tree * node,
724 			    tree   name,
725 			    tree   args,
726 			    int    flags ATTRIBUTE_UNUSED,
727 			    bool * no_add_attrs)
728 {
729   gcc_assert (DECL_P (* node));
730   gcc_assert (args == NULL_TREE);
731 
732   if (TREE_CODE (* node) != FUNCTION_DECL)
733     {
734       warning (OPT_Wattributes, "%qE attribute only applies to functions",
735 	       name);
736       * no_add_attrs = true;
737     }
738 
739   /* FIXME: We ought to check that the interrupt and exception
740      handler attributes have been applied to void functions.  */
741   return NULL_TREE;
742 }
743 
744 /* Check "naked" attributes.  */
745 static tree
746 rl78_handle_naked_attribute (tree * node,
747 			     tree   name ATTRIBUTE_UNUSED,
748 			     tree   args,
749 			     int    flags ATTRIBUTE_UNUSED,
750 			     bool * no_add_attrs)
751 {
752   gcc_assert (DECL_P (* node));
753   gcc_assert (args == NULL_TREE);
754 
755   if (TREE_CODE (* node) != FUNCTION_DECL)
756     {
757       warning (OPT_Wattributes, "naked attribute only applies to functions");
758       * no_add_attrs = true;
759     }
760 
761   /* Disable warnings about this function - eg reaching the end without
762      seeing a return statement - because the programmer is doing things
763      that gcc does not know about.  */
764   TREE_NO_WARNING (* node) = 1;
765 
766   return NULL_TREE;
767 }
768 
769 /* Check "saddr" attributes.  */
770 static tree
771 rl78_handle_saddr_attribute (tree * node,
772 			     tree   name,
773 			     tree   args ATTRIBUTE_UNUSED,
774 			     int    flags ATTRIBUTE_UNUSED,
775 			     bool * no_add_attrs)
776 {
777   gcc_assert (DECL_P (* node));
778 
779   if (TREE_CODE (* node) == FUNCTION_DECL)
780     {
781       warning (OPT_Wattributes, "%qE attribute doesn't apply to functions",
782 	       name);
783       * no_add_attrs = true;
784     }
785 
786   return NULL_TREE;
787 }
788 
789 #undef  TARGET_ATTRIBUTE_TABLE
790 #define TARGET_ATTRIBUTE_TABLE		rl78_attribute_table
791 
792 /* Table of RL78-specific attributes.  */
793 const struct attribute_spec rl78_attribute_table[] =
794 {
795   /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
796      affects_type_identity.  */
797   { "interrupt",      0, 0, true, false, false, rl78_handle_func_attribute,
798     false },
799   { "brk_interrupt",  0, 0, true, false, false, rl78_handle_func_attribute,
800     false },
801   { "naked",          0, 0, true, false, false, rl78_handle_naked_attribute,
802     false },
803   { "saddr",          0, 0, true, false, false, rl78_handle_saddr_attribute,
804     false },
805   { NULL,             0, 0, false, false, false, NULL, false }
806 };
807 
808 
809 
810 /* Break down an address RTX into its component base/index/addend
811    portions and return TRUE if the address is of a valid form, else
812    FALSE.  */
813 static bool
814 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
815 {
816   *base = NULL_RTX;
817   *index = NULL_RTX;
818   *addend = NULL_RTX;
819 
820   if (GET_CODE (x) == UNSPEC
821       && XINT (x, 1) == UNS_ES_ADDR)
822     x = XVECEXP (x, 0, 1);
823 
824   if (GET_CODE (x) == REG)
825     {
826       *base = x;
827       return true;
828     }
829 
830   /* We sometimes get these without the CONST wrapper */
831   if (GET_CODE (x) == PLUS
832       && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
833       && GET_CODE (XEXP (x, 1)) == CONST_INT)
834     {
835       *addend = x;
836       return true;
837     }
838 
839   if (GET_CODE (x) == PLUS)
840     {
841       *base = XEXP (x, 0);
842       x = XEXP (x, 1);
843 
844       if (GET_CODE (*base) == SUBREG)
845 	{
846 	  if (GET_MODE (*base) == HImode
847 	      && GET_MODE (XEXP (*base, 0)) == SImode
848 	      && GET_CODE (XEXP (*base, 0)) == REG)
849 	    {
850 	      /* This is a throw-away rtx just to tell everyone
851 		 else what effective register we're using.  */
852 	      *base = gen_rtx_REG (HImode, REGNO (XEXP (*base, 0)));
853 	    }
854 	}
855 
856       if (GET_CODE (*base) != REG
857 	  && GET_CODE (x) == REG)
858 	{
859 	  rtx tmp = *base;
860 	  *base = x;
861 	  x = tmp;
862 	}
863 
864       if (GET_CODE (*base) != REG)
865 	return false;
866 
867       if (GET_CODE (x) == ZERO_EXTEND
868 	  && GET_CODE (XEXP (x, 0)) == REG)
869 	{
870 	  *index = XEXP (x, 0);
871 	  return false;
872 	}
873     }
874 
875   switch (GET_CODE (x))
876     {
877     case PLUS:
878       if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
879 	  && GET_CODE (XEXP (x, 0)) == CONST_INT)
880 	{
881 	  *addend = x;
882 	  return true;
883 	}
884       /* fall through */
885     case MEM:
886     case REG:
887       return false;
888 
889     case SUBREG:
890       switch (GET_CODE (XEXP (x, 0)))
891 	{
892 	case CONST:
893 	case SYMBOL_REF:
894 	case CONST_INT:
895 	  *addend = x;
896 	  return true;
897 	default:
898 	  return false;
899 	}
900 
901     case CONST:
902     case SYMBOL_REF:
903     case CONST_INT:
904       *addend = x;
905       return true;
906 
907     default:
908       return false;
909     }
910 
911   return false;
912 }
913 
914 /* Used by the Whb constraint.  Match addresses that use HL+B or HL+C
915    addressing.  */
916 bool
917 rl78_hl_b_c_addr_p (rtx op)
918 {
919   rtx hl, bc;
920 
921   if (GET_CODE (op) != PLUS)
922     return false;
923   hl = XEXP (op, 0);
924   bc = XEXP (op, 1);
925   if (GET_CODE (hl) == ZERO_EXTEND)
926     {
927       rtx tmp = hl;
928       hl = bc;
929       bc = tmp;
930     }
931   if (GET_CODE (hl) != REG)
932     return false;
933   if (GET_CODE (bc) != ZERO_EXTEND)
934     return false;
935   bc = XEXP (bc, 0);
936   if (GET_CODE (bc) != REG)
937     return false;
938   if (REGNO (hl) != HL_REG)
939     return false;
940   if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
941     return false;
942 
943   return true;
944 }
945 
946 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
947 
948 /* Return the appropriate mode for a named address address.  */
949 
950 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
951 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
952 
953 static enum machine_mode
954 rl78_addr_space_address_mode (addr_space_t addrspace)
955 {
956   switch (addrspace)
957     {
958     case ADDR_SPACE_GENERIC:
959       return HImode;
960     case ADDR_SPACE_NEAR:
961       return HImode;
962     case ADDR_SPACE_FAR:
963       return SImode;
964     default:
965       gcc_unreachable ();
966     }
967 }
968 
969 /* Used in various constraints and predicates to match operands in the
970    "far" address space.  */
971 int
972 rl78_far_p (rtx x)
973 {
974   if (! MEM_P (x))
975     return 0;
976 #if DEBUG0
977   fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
978   fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
979 #endif
980 
981   /* Not all far addresses are legitimate, because the devirtualizer
982      can't handle them.  */
983   if (! rl78_as_legitimate_address (GET_MODE (x), XEXP (x, 0), false, ADDR_SPACE_FAR))
984     return 0;
985 
986   return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x))) == 32;
987 }
988 
989 /* Return the appropriate mode for a named address pointer.  */
990 #undef  TARGET_ADDR_SPACE_POINTER_MODE
991 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
992 
993 static machine_mode
994 rl78_addr_space_pointer_mode (addr_space_t addrspace)
995 {
996   switch (addrspace)
997     {
998     case ADDR_SPACE_GENERIC:
999       return HImode;
1000     case ADDR_SPACE_NEAR:
1001       return HImode;
1002     case ADDR_SPACE_FAR:
1003       return SImode;
1004     default:
1005       gcc_unreachable ();
1006     }
1007 }
1008 
1009 /* Returns TRUE for valid addresses.  */
1010 #undef  TARGET_VALID_POINTER_MODE
1011 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1012 
1013 static bool
1014 rl78_valid_pointer_mode (machine_mode m)
1015 {
1016   return (m == HImode || m == SImode);
1017 }
1018 
1019 #undef  TARGET_LEGITIMATE_CONSTANT_P
1020 #define TARGET_LEGITIMATE_CONSTANT_P		rl78_is_legitimate_constant
1021 
1022 static bool
1023 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
1024 {
1025   return true;
1026 }
1027 
1028 #undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1029 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P	rl78_as_legitimate_address
1030 
1031 bool
1032 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
1033 			    bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
1034 {
1035   rtx base, index, addend;
1036   bool is_far_addr = false;
1037   int as_bits;
1038 
1039   as_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (as));
1040 
1041   if (GET_CODE (x) == UNSPEC
1042       && XINT (x, 1) == UNS_ES_ADDR)
1043     {
1044       x = XVECEXP (x, 0, 1);
1045       is_far_addr = true;
1046     }
1047 
1048   if (as_bits == 16 && is_far_addr)
1049     return false;
1050 
1051   if (! characterize_address (x, &base, &index, &addend))
1052     return false;
1053 
1054   /* We can't extract the high/low portions of a PLUS address
1055      involving a register during devirtualization, so make sure all
1056      such __far addresses do not have addends.  This forces GCC to do
1057      the sum separately.  */
1058   if (addend && base && as_bits == 32 && GET_MODE (base) == SImode)
1059     return false;
1060 
1061   if (base && index)
1062     {
1063       int ir = REGNO (index);
1064       int br = REGNO (base);
1065 
1066 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1067       OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
1068       OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
1069       return false;
1070     }
1071 
1072   if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
1073     return false;
1074 
1075   if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
1076       && REGNO (base) >= 8 && REGNO (base) <= 31)
1077     return false;
1078 
1079   return true;
1080 }
1081 
1082 /* Determine if one named address space is a subset of another.  */
1083 #undef  TARGET_ADDR_SPACE_SUBSET_P
1084 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1085 
1086 static bool
1087 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1088 {
1089   int subset_bits;
1090   int superset_bits;
1091 
1092   subset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset));
1093   superset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset));
1094 
1095   return (subset_bits <= superset_bits);
1096 }
1097 
1098 #undef  TARGET_ADDR_SPACE_CONVERT
1099 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1100 
1101 /* Convert from one address space to another.  */
1102 static rtx
1103 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
1104 {
1105   addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1106   addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1107   rtx result;
1108   int to_bits;
1109   int from_bits;
1110 
1111   to_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as));
1112   from_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as));
1113 
1114   if (to_bits < from_bits)
1115     {
1116       rtx tmp;
1117       /* This is unpredictable, as we're truncating off usable address
1118 	 bits.  */
1119 
1120       warning (OPT_Waddress, "converting far pointer to near pointer");
1121       result = gen_reg_rtx (HImode);
1122       if (GET_CODE (op) == SYMBOL_REF
1123 	  || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER))
1124 	tmp = gen_rtx_raw_SUBREG (HImode, op, 0);
1125       else
1126 	tmp = simplify_subreg (HImode, op, SImode, 0);
1127       gcc_assert (tmp != NULL_RTX);
1128       emit_move_insn (result, tmp);
1129       return result;
1130     }
1131   else if (to_bits > from_bits)
1132     {
1133       /* This always works.  */
1134       result = gen_reg_rtx (SImode);
1135       emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
1136       if (TREE_CODE (from_type) == POINTER_TYPE
1137 	  && TREE_CODE (TREE_TYPE (from_type)) == FUNCTION_TYPE)
1138 	emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
1139       else
1140 	emit_move_insn (rl78_subreg (HImode, result, SImode, 2), GEN_INT (0x0f));
1141       return result;
1142     }
1143   else
1144     return op;
1145   gcc_unreachable ();
1146 }
1147 
1148 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P.  */
1149 bool
1150 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
1151 				    addr_space_t address_space ATTRIBUTE_UNUSED,
1152 				    int outer_code ATTRIBUTE_UNUSED, int index_code)
1153 {
1154   if (regno <= SP_REG && regno >= 16)
1155     return true;
1156   if (index_code == REG)
1157     return (regno == HL_REG);
1158   if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
1159     return true;
1160   return false;
1161 }
1162 
1163 /* Implements MODE_CODE_BASE_REG_CLASS.  */
1164 enum reg_class
1165 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1166 			       addr_space_t address_space ATTRIBUTE_UNUSED,
1167 			       int outer_code ATTRIBUTE_UNUSED,
1168 			       int index_code ATTRIBUTE_UNUSED)
1169 {
1170   return V_REGS;
1171 }
1172 
1173 /* Typical stack layout should looks like this after the function's prologue:
1174 
1175                             |    |
1176                               --                       ^
1177                             |    | \                   |
1178                             |    |   arguments saved   | Increasing
1179                             |    |   on the stack      |  addresses
1180     PARENT   arg pointer -> |    | /
1181   -------------------------- ---- -------------------
1182     CHILD                   |ret |   return address
1183                               --
1184                             |    | \
1185                             |    |   call saved
1186                             |    |   registers
1187 	frame pointer ->    |    | /
1188                               --
1189                             |    | \
1190                             |    |   local
1191                             |    |   variables
1192                             |    | /
1193                               --
1194                             |    | \
1195                             |    |   outgoing          | Decreasing
1196                             |    |   arguments         |  addresses
1197    current stack pointer -> |    | /                   |
1198   -------------------------- ---- ------------------   V
1199                             |    |                 */
1200 
1201 /* Implements INITIAL_ELIMINATION_OFFSET.  The frame layout is
1202    described in the machine_Function struct definition, above.  */
1203 int
1204 rl78_initial_elimination_offset (int from, int to)
1205 {
1206   int rv = 0; /* as if arg to arg */
1207 
1208   rl78_compute_frame_info ();
1209 
1210   switch (to)
1211     {
1212     case STACK_POINTER_REGNUM:
1213       rv += cfun->machine->framesize_outgoing;
1214       rv += cfun->machine->framesize_locals;
1215       /* Fall through.  */
1216     case FRAME_POINTER_REGNUM:
1217       rv += cfun->machine->framesize_regs;
1218       rv += 4;
1219       break;
1220     default:
1221       gcc_unreachable ();
1222     }
1223 
1224   switch (from)
1225     {
1226     case FRAME_POINTER_REGNUM:
1227       rv -= 4;
1228       rv -= cfun->machine->framesize_regs;
1229     case ARG_POINTER_REGNUM:
1230       break;
1231     default:
1232       gcc_unreachable ();
1233     }
1234 
1235   return rv;
1236 }
1237 
1238 static int
1239 rl78_is_naked_func (void)
1240 {
1241   return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1242 }
1243 
1244 /* Expand the function prologue (from the prologue pattern).  */
1245 void
1246 rl78_expand_prologue (void)
1247 {
1248   int i, fs;
1249   rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1250   rtx ax = gen_rtx_REG (HImode, AX_REG);
1251   int rb = 0;
1252 
1253   if (rl78_is_naked_func ())
1254     return;
1255 
1256   /* Always re-compute the frame info - the register usage may have changed.  */
1257   rl78_compute_frame_info ();
1258 
1259   if (flag_stack_usage_info)
1260     current_function_static_stack_size = cfun->machine->framesize;
1261 
1262   if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1263     for (i = 0; i < 4; i++)
1264       if (cfun->machine->need_to_push [i])
1265 	{
1266 	  /* Select Bank 0 if we are using any registers from Bank 0.   */
1267 	  emit_insn (gen_sel_rb (GEN_INT (0)));
1268 	  break;
1269 	}
1270 
1271   for (i = 0; i < 16; i++)
1272     if (cfun->machine->need_to_push [i])
1273       {
1274 	int reg = i * 2;
1275 
1276 	if (TARGET_G10)
1277 	  {
1278 	    if (reg >= 8)
1279 	      {
1280 		emit_move_insn (ax, gen_rtx_REG (HImode, reg));
1281 		reg = AX_REG;
1282 	      }
1283 	  }
1284 	else
1285 	  {
1286 	    int need_bank = i/4;
1287 
1288 	    if (need_bank != rb)
1289 	      {
1290 		emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1291 		rb = need_bank;
1292 	      }
1293 	  }
1294 
1295 	F (emit_insn (gen_push (gen_rtx_REG (HImode, reg))));
1296       }
1297 
1298   if (rb != 0)
1299     emit_insn (gen_sel_rb (GEN_INT (0)));
1300 
1301   /* Save ES register inside interrupt functions if it is used.  */
1302   if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1303     {
1304       emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG)));
1305       F (emit_insn (gen_push (ax)));
1306     }
1307 
1308   if (frame_pointer_needed)
1309     {
1310       F (emit_move_insn (ax, sp));
1311       F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM), ax));
1312     }
1313 
1314   fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1315   if (fs > 0)
1316     {
1317       /* If we need to subtract more than 254*3 then it is faster and
1318 	 smaller to move SP into AX and perform the subtraction there.  */
1319       if (fs > 254 * 3)
1320 	{
1321 	  rtx insn;
1322 
1323 	  emit_move_insn (ax, sp);
1324 	  emit_insn (gen_subhi3 (ax, ax, GEN_INT (fs)));
1325 	  insn = emit_move_insn (sp, ax);
1326 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1327 			gen_rtx_SET (SImode, sp,
1328 				     gen_rtx_PLUS (HImode, sp, GEN_INT (-fs))));
1329 	}
1330       else
1331 	{
1332 	  while (fs > 0)
1333 	    {
1334 	      int fs_byte = (fs > 254) ? 254 : fs;
1335 
1336 	      F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1337 	      fs -= fs_byte;
1338 	    }
1339 	}
1340     }
1341 }
1342 
1343 /* Expand the function epilogue (from the epilogue pattern).  */
1344 void
1345 rl78_expand_epilogue (void)
1346 {
1347   int i, fs;
1348   rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1349   rtx ax = gen_rtx_REG (HImode, AX_REG);
1350   int rb = 0;
1351 
1352   if (rl78_is_naked_func ())
1353     return;
1354 
1355   if (frame_pointer_needed)
1356     {
1357       emit_move_insn (ax, gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1358       emit_move_insn (sp, ax);
1359     }
1360   else
1361     {
1362       fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1363       if (fs > 254 * 3)
1364 	{
1365 	  emit_move_insn (ax, sp);
1366 	  emit_insn (gen_addhi3 (ax, ax, GEN_INT (fs)));
1367 	  emit_move_insn (sp, ax);
1368 	}
1369       else
1370 	{
1371 	  while (fs > 0)
1372 	    {
1373 	      int fs_byte = (fs > 254) ? 254 : fs;
1374 
1375 	      emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1376 	      fs -= fs_byte;
1377 	    }
1378 	}
1379     }
1380 
1381   if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1382     {
1383       emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1384       emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode, A_REG)));
1385     }
1386 
1387   for (i = 15; i >= 0; i--)
1388     if (cfun->machine->need_to_push [i])
1389       {
1390 	rtx dest = gen_rtx_REG (HImode, i * 2);
1391 
1392 	if (TARGET_G10)
1393 	  {
1394 	    if (i < 8)
1395 	      emit_insn (gen_pop (dest));
1396 	    else
1397 	      {
1398 		emit_insn (gen_pop (ax));
1399 		emit_move_insn (dest, ax);
1400 		/* Generate a USE of the pop'd register so that DCE will not eliminate the move.  */
1401 		emit_insn (gen_use (dest));
1402 	      }
1403 	  }
1404 	else
1405 	  {
1406 	    int need_bank = i / 4;
1407 
1408 	    if (need_bank != rb)
1409 	      {
1410 		emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1411 		rb = need_bank;
1412 	      }
1413 	    emit_insn (gen_pop (dest));
1414 	  }
1415       }
1416 
1417   if (rb != 0)
1418     emit_insn (gen_sel_rb (GEN_INT (0)));
1419 
1420   if (cfun->machine->trampolines_used)
1421     emit_insn (gen_trampoline_uninit ());
1422 
1423   if (is_brk_interrupt_func (cfun->decl))
1424     emit_jump_insn (gen_brk_interrupt_return ());
1425   else if (is_interrupt_func (cfun->decl))
1426     emit_jump_insn (gen_interrupt_return ());
1427   else
1428     emit_jump_insn (gen_rl78_return ());
1429 }
1430 
1431 /* Likewise, for exception handlers.  */
1432 void
1433 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1434 {
1435   /* FIXME - replace this with an indirect jump with stack adjust.  */
1436   emit_jump_insn (gen_rl78_return ());
1437 }
1438 
1439 #undef  TARGET_ASM_FUNCTION_PROLOGUE
1440 #define TARGET_ASM_FUNCTION_PROLOGUE	rl78_start_function
1441 
1442 /* We don't use this to actually emit the function prologue.  We use
1443    this to insert a comment in the asm file describing the
1444    function.  */
1445 static void
1446 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1447 {
1448   int i;
1449 
1450   if (cfun->machine->framesize == 0)
1451     return;
1452   fprintf (file, "\t; start of function\n");
1453 
1454   if (cfun->machine->framesize_regs)
1455     {
1456       fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1457       for (i = 0; i < 16; i ++)
1458 	if (cfun->machine->need_to_push[i])
1459 	  fprintf (file, " %s", word_regnames[i*2]);
1460       fprintf (file, "\n");
1461     }
1462 
1463   if (frame_pointer_needed)
1464     fprintf (file, "\t; $fp points here (r22)\n");
1465 
1466   if (cfun->machine->framesize_locals)
1467     fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1468 	     cfun->machine->framesize_locals == 1 ? "" : "s");
1469 
1470   if (cfun->machine->framesize_outgoing)
1471     fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1472 	     cfun->machine->framesize_outgoing == 1 ? "" : "s");
1473 
1474   if (cfun->machine->uses_es)
1475     fprintf (file, "\t; uses ES register\n");
1476 }
1477 
1478 /* Return an RTL describing where a function return value of type RET_TYPE
1479    is held.  */
1480 
1481 #undef  TARGET_FUNCTION_VALUE
1482 #define TARGET_FUNCTION_VALUE		rl78_function_value
1483 
1484 static rtx
1485 rl78_function_value (const_tree ret_type,
1486 		     const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1487 		     bool       outgoing ATTRIBUTE_UNUSED)
1488 {
1489   machine_mode mode = TYPE_MODE (ret_type);
1490 
1491   return gen_rtx_REG (mode, 8);
1492 }
1493 
1494 #undef  TARGET_PROMOTE_FUNCTION_MODE
1495 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1496 
1497 static machine_mode
1498 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1499 			    machine_mode mode,
1500 			    int *punsignedp ATTRIBUTE_UNUSED,
1501 			    const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1502 {
1503   return mode;
1504 }
1505 
1506 /* Return an RTL expression describing the register holding a function
1507    parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1508    be passed on the stack.  CUM describes the previous parameters to the
1509    function and NAMED is false if the parameter is part of a variable
1510    parameter list, or the last named parameter before the start of a
1511    variable parameter list.  */
1512 
1513 #undef  TARGET_FUNCTION_ARG
1514 #define TARGET_FUNCTION_ARG     	rl78_function_arg
1515 
1516 static rtx
1517 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1518 		   machine_mode mode ATTRIBUTE_UNUSED,
1519 		   const_tree type ATTRIBUTE_UNUSED,
1520 		   bool named ATTRIBUTE_UNUSED)
1521 {
1522   return NULL_RTX;
1523 }
1524 
1525 #undef  TARGET_FUNCTION_ARG_ADVANCE
1526 #define TARGET_FUNCTION_ARG_ADVANCE     rl78_function_arg_advance
1527 
1528 static void
1529 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1530 			   bool named ATTRIBUTE_UNUSED)
1531 {
1532   int rounded_size;
1533   CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1534 
1535   rounded_size = ((mode == BLKmode)
1536 		  ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1537   if (rounded_size & 1)
1538     rounded_size ++;
1539   (*cum) += rounded_size;
1540 }
1541 
1542 #undef  TARGET_FUNCTION_ARG_BOUNDARY
1543 #define	TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1544 
1545 static unsigned int
1546 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1547 			    const_tree type ATTRIBUTE_UNUSED)
1548 {
1549   return 16;
1550 }
1551 
1552 /* Supported modifier letters:
1553 
1554    A - address of a MEM
1555    S - SADDR form of a real register
1556    v - real register corresponding to a virtual register
1557    m - minus - negative of CONST_INT value.
1558    C - inverse of a conditional (NE vs EQ for example)
1559    C - complement of an integer
1560    z - collapsed conditional
1561    s - shift count mod 8
1562    S - shift count mod 16
1563    r - reverse shift count (8-(count mod 8))
1564    B - bit position
1565 
1566    h - bottom HI of an SI
1567    H - top HI of an SI
1568    q - bottom QI of an HI
1569    Q - top QI of an HI
1570    e - third QI of an SI (i.e. where the ES register gets values from)
1571    E - fourth QI of an SI (i.e. MSB)
1572 
1573 */
1574 
1575 /* Implements the bulk of rl78_print_operand, below.  We do it this
1576    way because we need to test for a constant at the top level and
1577    insert the '#', but not test for it anywhere else as we recurse
1578    down into the operand.  */
1579 static void
1580 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1581 {
1582   int need_paren;
1583 
1584   switch (GET_CODE (op))
1585     {
1586     case MEM:
1587       if (letter == 'A')
1588 	rl78_print_operand_1 (file, XEXP (op, 0), letter);
1589       else
1590 	{
1591 	  if (rl78_far_p (op))
1592 	    {
1593 	      fprintf (file, "es:");
1594 	      if (GET_CODE (XEXP (op, 0)) == UNSPEC)
1595 		op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1596 	    }
1597 	  if (letter == 'H')
1598 	    {
1599 	      op = adjust_address (op, HImode, 2);
1600 	      letter = 0;
1601 	    }
1602 	  if (letter == 'h')
1603 	    {
1604 	      op = adjust_address (op, HImode, 0);
1605 	      letter = 0;
1606 	    }
1607 	  if (letter == 'Q')
1608 	    {
1609 	      op = adjust_address (op, QImode, 1);
1610 	      letter = 0;
1611 	    }
1612 	  if (letter == 'q')
1613 	    {
1614 	      op = adjust_address (op, QImode, 0);
1615 	      letter = 0;
1616 	    }
1617 	  if (letter == 'e')
1618 	    {
1619 	      op = adjust_address (op, QImode, 2);
1620 	      letter = 0;
1621 	    }
1622 	  if (letter == 'E')
1623 	    {
1624 	      op = adjust_address (op, QImode, 3);
1625 	      letter = 0;
1626 	    }
1627 	  if (CONSTANT_P (XEXP (op, 0)))
1628 	    {
1629 	      if (!rl78_saddr_p (op))
1630 		fprintf (file, "!");
1631 	      rl78_print_operand_1 (file, XEXP (op, 0), letter);
1632 	    }
1633 	  else if (GET_CODE (XEXP (op, 0)) == PLUS
1634 		   && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1635 	    {
1636 	      if (!rl78_saddr_p (op))
1637 		fprintf (file, "!");
1638 	      rl78_print_operand_1 (file, XEXP (op, 0), letter);
1639 	    }
1640 	  else if (GET_CODE (XEXP (op, 0)) == PLUS
1641 		   && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1642 		   && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1643 	    {
1644 	      rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1645 	      fprintf (file, "[");
1646 	      rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1647 	      fprintf (file, "]");
1648 	    }
1649 	  else
1650 	    {
1651 	      fprintf (file, "[");
1652 	      rl78_print_operand_1 (file, XEXP (op, 0), letter);
1653 	      if (letter == 'p' && GET_CODE (XEXP (op, 0)) == REG)
1654 		fprintf (file, "+0");
1655 	      fprintf (file, "]");
1656 	    }
1657 	}
1658       break;
1659 
1660     case REG:
1661       if (letter == 'Q')
1662 	fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1663       else if (letter == 'H')
1664 	fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1665       else if (letter == 'q')
1666 	fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1667       else if (letter == 'e')
1668 	fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1669       else if (letter == 'E')
1670 	fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1671       else if (letter == 'S')
1672 	fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1673       else if (GET_MODE (op) == HImode
1674 	       && ! (REGNO (op) & ~0xfe))
1675 	{
1676 	  if (letter == 'v')
1677 	    fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1678 	  else
1679 	    fprintf (file, "%s", word_regnames [REGNO (op)]);
1680 	}
1681       else
1682 	fprintf (file, "%s", reg_names [REGNO (op)]);
1683       break;
1684 
1685     case CONST_INT:
1686       if (letter == 'Q')
1687 	fprintf (file, "%ld", INTVAL (op) >> 8);
1688       else if (letter == 'H')
1689 	fprintf (file, "%ld", INTVAL (op) >> 16);
1690       else if (letter == 'q')
1691 	fprintf (file, "%ld", INTVAL (op) & 0xff);
1692       else if (letter == 'h')
1693 	fprintf (file, "%ld", INTVAL (op) & 0xffff);
1694       else if (letter == 'e')
1695 	fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1696       else if (letter == 'B')
1697 	{
1698 	  int ival = INTVAL (op);
1699 	  if (ival == -128)
1700 	    ival = 0x80;
1701 	  if (exact_log2 (ival) >= 0)
1702 	    fprintf (file, "%d", exact_log2 (ival));
1703 	  else
1704 	    fprintf (file, "%d", exact_log2 (~ival & 0xff));
1705 	}
1706       else if (letter == 'E')
1707 	fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1708       else if (letter == 'm')
1709 	fprintf (file, "%ld", - INTVAL (op));
1710       else if (letter == 's')
1711 	fprintf (file, "%ld", INTVAL (op) % 8);
1712       else if (letter == 'S')
1713 	fprintf (file, "%ld", INTVAL (op) % 16);
1714       else if (letter == 'r')
1715 	fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1716       else if (letter == 'C')
1717 	fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1718       else
1719 	fprintf (file, "%ld", INTVAL (op));
1720       break;
1721 
1722     case CONST:
1723       rl78_print_operand_1 (file, XEXP (op, 0), letter);
1724       break;
1725 
1726     case ZERO_EXTRACT:
1727       {
1728 	int bits = INTVAL (XEXP (op, 1));
1729 	int ofs = INTVAL (XEXP (op, 2));
1730 	if (bits == 16 && ofs == 0)
1731 	  fprintf (file, "%%lo16(");
1732 	else if (bits == 16 && ofs == 16)
1733 	  fprintf (file, "%%hi16(");
1734 	else if (bits == 8 && ofs == 16)
1735 	  fprintf (file, "%%hi8(");
1736 	else
1737 	  gcc_unreachable ();
1738 	rl78_print_operand_1 (file, XEXP (op, 0), 0);
1739 	fprintf (file, ")");
1740       }
1741       break;
1742 
1743     case ZERO_EXTEND:
1744       if (GET_CODE (XEXP (op, 0)) == REG)
1745 	fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1746       else
1747 	print_rtl (file, op);
1748       break;
1749 
1750     case PLUS:
1751       need_paren = 0;
1752       if (letter == 'H')
1753 	{
1754 	  fprintf (file, "%%hi16(");
1755 	  need_paren = 1;
1756 	  letter = 0;
1757 	}
1758       if (letter == 'h')
1759 	{
1760 	  fprintf (file, "%%lo16(");
1761 	  need_paren = 1;
1762 	  letter = 0;
1763 	}
1764       if (letter == 'e')
1765 	{
1766 	  fprintf (file, "%%hi8(");
1767 	  need_paren = 1;
1768 	  letter = 0;
1769 	}
1770       if (letter == 'q' || letter == 'Q')
1771 	output_operand_lossage ("q/Q modifiers invalid for symbol references");
1772 
1773       if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1774 	{
1775 	  rl78_print_operand_1 (file, XEXP (op, 1), letter);
1776 	  fprintf (file, "+");
1777 	  rl78_print_operand_1 (file, XEXP (op, 0), letter);
1778 	}
1779       else
1780 	{
1781 	  rl78_print_operand_1 (file, XEXP (op, 0), letter);
1782 	  fprintf (file, "+");
1783 	  rl78_print_operand_1 (file, XEXP (op, 1), letter);
1784 	}
1785       if (need_paren)
1786 	fprintf (file, ")");
1787       break;
1788 
1789     case SUBREG:
1790       if (GET_MODE (op) == HImode
1791 	  && SUBREG_BYTE (op) == 0)
1792 	{
1793 	  fprintf (file, "%%lo16(");
1794 	  rl78_print_operand_1 (file, SUBREG_REG (op), 0);
1795 	  fprintf (file, ")");
1796 	}
1797       else if (GET_MODE (op) == HImode
1798 	       && SUBREG_BYTE (op) == 2)
1799 	{
1800 	  fprintf (file, "%%hi16(");
1801 	  rl78_print_operand_1 (file, SUBREG_REG (op), 0);
1802 	  fprintf (file, ")");
1803 	}
1804       else
1805 	{
1806 	  fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1807 	}
1808       break;
1809 
1810     case SYMBOL_REF:
1811       need_paren = 0;
1812       if (letter == 'H')
1813 	{
1814 	  fprintf (file, "%%hi16(");
1815 	  need_paren = 1;
1816 	  letter = 0;
1817 	}
1818       if (letter == 'h')
1819 	{
1820 	  fprintf (file, "%%lo16(");
1821 	  need_paren = 1;
1822 	  letter = 0;
1823 	}
1824       if (letter == 'e')
1825 	{
1826 	  fprintf (file, "%%hi8(");
1827 	  need_paren = 1;
1828 	  letter = 0;
1829 	}
1830       if (letter == 'q' || letter == 'Q')
1831 	output_operand_lossage ("q/Q modifiers invalid for symbol references");
1832 
1833       if (SYMBOL_REF_DECL (op) && TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL)
1834 	{
1835 	  fprintf (file, "%%code(");
1836 	  assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
1837 	  fprintf (file, ")");
1838 	}
1839       else
1840         assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
1841       if (need_paren)
1842 	fprintf (file, ")");
1843       break;
1844 
1845     case CODE_LABEL:
1846     case LABEL_REF:
1847       output_asm_label (op);
1848       break;
1849 
1850     case LTU:
1851       if (letter == 'z')
1852 	fprintf (file, "#comparison eliminated");
1853       else
1854 	fprintf (file, letter == 'C' ? "nc" : "c");
1855       break;
1856     case LEU:
1857       if (letter == 'z')
1858 	fprintf (file, "br");
1859       else
1860 	fprintf (file, letter == 'C' ? "h" : "nh");
1861       break;
1862     case GEU:
1863       if (letter == 'z')
1864 	fprintf (file, "br");
1865       else
1866 	fprintf (file, letter == 'C' ? "c" : "nc");
1867       break;
1868     case GTU:
1869       if (letter == 'z')
1870 	fprintf (file, "#comparison eliminated");
1871       else
1872 	fprintf (file, letter == 'C' ? "nh" : "h");
1873       break;
1874     case EQ:
1875       if (letter == 'z')
1876 	fprintf (file, "br");
1877       else
1878 	fprintf (file, letter == 'C' ? "nz" : "z");
1879       break;
1880     case NE:
1881       if (letter == 'z')
1882 	fprintf (file, "#comparison eliminated");
1883       else
1884 	fprintf (file, letter == 'C' ? "z" : "nz");
1885       break;
1886 
1887     /* Note: these assume appropriate adjustments were made so that
1888        unsigned comparisons, which is all this chip has, will
1889        work.  */
1890     case LT:
1891       if (letter == 'z')
1892 	fprintf (file, "#comparison eliminated");
1893       else
1894 	fprintf (file, letter == 'C' ? "nc" : "c");
1895       break;
1896     case LE:
1897       if (letter == 'z')
1898 	fprintf (file, "br");
1899       else
1900         fprintf (file, letter == 'C' ? "h" : "nh");
1901       break;
1902     case GE:
1903       if (letter == 'z')
1904 	fprintf (file, "br");
1905       else
1906 	fprintf (file, letter == 'C' ? "c" : "nc");
1907       break;
1908     case GT:
1909       if (letter == 'z')
1910 	fprintf (file, "#comparison eliminated");
1911       else
1912 	fprintf (file, letter == 'C' ? "nh" : "h");
1913       break;
1914 
1915     default:
1916       fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1917       break;
1918     }
1919 }
1920 
1921 #undef  TARGET_PRINT_OPERAND
1922 #define TARGET_PRINT_OPERAND		rl78_print_operand
1923 
1924 static void
1925 rl78_print_operand (FILE * file, rtx op, int letter)
1926 {
1927   if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
1928     fprintf (file, "#");
1929   rl78_print_operand_1 (file, op, letter);
1930 }
1931 
1932 #undef  TARGET_TRAMPOLINE_INIT
1933 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1934 
1935 /* Note that the RL78's addressing makes it very difficult to do
1936    trampolines on the stack.  So, libgcc has a small pool of
1937    trampolines from which one is allocated to this task.  */
1938 static void
1939 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1940 {
1941   rtx mov_addr, thunk_addr;
1942   rtx function = XEXP (DECL_RTL (fndecl), 0);
1943 
1944   mov_addr = adjust_address (m_tramp, HImode, 0);
1945   thunk_addr = gen_reg_rtx (HImode);
1946 
1947   function = force_reg (HImode, function);
1948   static_chain = force_reg (HImode, static_chain);
1949 
1950   emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1951   emit_move_insn (mov_addr, thunk_addr);
1952 
1953   cfun->machine->trampolines_used = 1;
1954 }
1955 
1956 #undef  TARGET_TRAMPOLINE_ADJUST_ADDRESS
1957 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1958 
1959 static rtx
1960 rl78_trampoline_adjust_address (rtx m_tramp)
1961 {
1962   rtx x = gen_rtx_MEM (HImode, m_tramp);
1963   return x;
1964 }
1965 
1966 /* Expander for cbranchqi4 and cbranchhi4.  RL78 is missing some of
1967    the "normal" compares, specifically, it only has unsigned compares,
1968    so we must synthesize the missing ones.  */
1969 void
1970 rl78_expand_compare (rtx *operands)
1971 {
1972   if (GET_CODE (operands[2]) == MEM)
1973     operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1974 }
1975 
1976 
1977 
1978 /* Define this to 1 if you are debugging the peephole optimizers.  */
1979 #define DEBUG_PEEP 0
1980 
1981 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1982    The default "word" size is a byte so we can effectively use all the
1983    registers, but we want to do 16-bit moves whenever possible.  This
1984    function determines when such a move is an option.  */
1985 bool
1986 rl78_peep_movhi_p (rtx *operands)
1987 {
1988   int i;
1989   rtx m, a;
1990 
1991   /* (set (op0) (op1))
1992      (set (op2) (op3)) */
1993 
1994   if (! rl78_virt_insns_ok ())
1995     return false;
1996 
1997 #if DEBUG_PEEP
1998   fprintf (stderr, "\033[33m");
1999   debug_rtx (operands[0]);
2000   debug_rtx (operands[1]);
2001   debug_rtx (operands[2]);
2002   debug_rtx (operands[3]);
2003   fprintf (stderr, "\033[0m");
2004 #endif
2005 
2006   /* You can move a constant to memory as QImode, but not HImode.  */
2007   if (GET_CODE (operands[0]) == MEM
2008       && GET_CODE (operands[1]) != REG)
2009     {
2010 #if DEBUG_PEEP
2011       fprintf (stderr, "no peep: move constant to memory\n");
2012 #endif
2013       return false;
2014     }
2015 
2016   if (rtx_equal_p (operands[0], operands[3]))
2017     {
2018 #if DEBUG_PEEP
2019       fprintf (stderr, "no peep: overlapping\n");
2020 #endif
2021       return false;
2022     }
2023 
2024   for (i = 0; i < 2; i ++)
2025     {
2026       if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
2027 	{
2028 #if DEBUG_PEEP
2029 	  fprintf (stderr, "no peep: different codes\n");
2030 #endif
2031 	  return false;
2032 	}
2033       if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
2034 	{
2035 #if DEBUG_PEEP
2036 	  fprintf (stderr, "no peep: different modes\n");
2037 #endif
2038 	  return false;
2039 	}
2040 
2041       switch (GET_CODE (operands[i]))
2042 	{
2043 	case REG:
2044 	  /*   LSB                      MSB  */
2045 	  if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
2046 	      || GET_MODE (operands[i]) != QImode)
2047 	    {
2048 #if DEBUG_PEEP
2049 	      fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
2050 		       REGNO (operands[i]), REGNO (operands[i+2]),
2051 		       i);
2052 #endif
2053 	      return false;
2054 	    }
2055 	  if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
2056 	    {
2057 #if DEBUG_PEEP
2058 	      fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
2059 #endif
2060 	      return false;
2061 	    }
2062 	  break;
2063 
2064 	case CONST_INT:
2065 	  break;
2066 
2067 	case MEM:
2068 	  if (GET_MODE (operands[i]) != QImode)
2069 	    return false;
2070 	  if (MEM_ALIGN (operands[i]) < 16)
2071 	    return false;
2072 	  a = XEXP (operands[i], 0);
2073 	  if (GET_CODE (a) == CONST)
2074 	    a = XEXP (a, 0);
2075 	  if (GET_CODE (a) == PLUS)
2076 	    a = XEXP (a, 1);
2077 	  if (GET_CODE (a) == CONST_INT
2078 	      && INTVAL (a) & 1)
2079 	    {
2080 #if DEBUG_PEEP
2081 	      fprintf (stderr, "no peep: misaligned mem %d\n", i);
2082 	      debug_rtx (operands[i]);
2083 #endif
2084 	      return false;
2085 	    }
2086 	  m = adjust_address (operands[i], QImode, 1);
2087 	  if (! rtx_equal_p (m, operands[i+2]))
2088 	    {
2089 #if DEBUG_PEEP
2090 	      fprintf (stderr, "no peep: wrong mem %d\n", i);
2091 	      debug_rtx (m);
2092 	      debug_rtx (operands[i+2]);
2093 #endif
2094 	      return false;
2095 	    }
2096 	  break;
2097 
2098 	default:
2099 #if DEBUG_PEEP
2100 	  fprintf (stderr, "no peep: wrong rtx %d\n", i);
2101 #endif
2102 	  return false;
2103 	}
2104     }
2105 #if DEBUG_PEEP
2106   fprintf (stderr, "\033[32mpeep!\033[0m\n");
2107 #endif
2108   return true;
2109 }
2110 
2111 /* Likewise, when a peephole is activated, this function helps compute
2112    the new operands.  */
2113 void
2114 rl78_setup_peep_movhi (rtx *operands)
2115 {
2116   int i;
2117 
2118   for (i = 0; i < 2; i ++)
2119     {
2120       switch (GET_CODE (operands[i]))
2121 	{
2122 	case REG:
2123 	  operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
2124 	  break;
2125 
2126 	case CONST_INT:
2127 	  operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
2128 	  break;
2129 
2130 	case MEM:
2131 	  operands[i+4] = adjust_address (operands[i], HImode, 0);
2132 	  break;
2133 
2134 	default:
2135 	  break;
2136 	}
2137     }
2138 }
2139 
2140 /*
2141 	How Devirtualization works in the RL78 GCC port
2142 
2143 Background
2144 
2145 The RL78 is an 8-bit port with some 16-bit operations.  It has 32
2146 bytes of register space, in four banks, memory-mapped.  One bank is
2147 the "selected" bank and holds the registers used for primary
2148 operations.  Since the registers are memory mapped, often you can
2149 still refer to the unselected banks via memory accesses.
2150 
2151 Virtual Registers
2152 
2153 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2154 and refers to the other banks via their memory addresses, although
2155 they're treated as regular registers internally.  These "virtual"
2156 registers are R8 through R23 (bank3 is reserved for asm-based
2157 interrupt handlers).
2158 
2159 There are four machine description files:
2160 
2161 rl78.md        - common register-independent patterns and definitions
2162 rl78-expand.md - expanders
2163 rl78-virt.md   - patterns that match BEFORE devirtualization
2164 rl78-real.md   - patterns that match AFTER devirtualization
2165 
2166 At least through register allocation and reload, gcc is told that it
2167 can do pretty much anything - but may only use the virtual registers.
2168 GCC cannot properly create the varying addressing modes that the RL78
2169 supports in an efficient way.
2170 
2171 Sometime after reload, the RL78 backend "devirtualizes" the RTL.  It
2172 uses the "valloc" attribute in rl78-virt.md for determining the rules
2173 by which it will replace virtual registers with real registers (or
2174 not) and how to make up addressing modes.  For example, insns tagged
2175 with "ro1" have a single read-only parameter, which may need to be
2176 moved from memory/constant/vreg to a suitable real register.  As part
2177 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2178 patterns and enabling the rl78-real.md patterns.  The new patterns'
2179 constraints are used to determine the real registers used.  NOTE:
2180 patterns in rl78-virt.md essentially ignore the constrains and rely on
2181 predicates, where the rl78-real.md ones essentially ignore the
2182 predicates and rely on the constraints.
2183 
2184 The devirtualization pass is scheduled via the pass manager (despite
2185 being called "rl78_reorg") so it can be scheduled prior to var-track
2186 (the idea is to let gdb know about the new registers).  Ideally, it
2187 would be scheduled right after pro/epilogue generation, so the
2188 post-reload optimizers could operate on the real registers, but when I
2189 tried that there were some issues building the target libraries.
2190 
2191 During devirtualization, a simple register move optimizer is run.  It
2192 would be better to run a full CSE/propogation pass on it though, but
2193 that has not yet been attempted.
2194 
2195  */
2196 #define DEBUG_ALLOC 0
2197 
2198 #define OP(x) (*recog_data.operand_loc[x])
2199 
2200 /* This array is used to hold knowledge about the contents of the
2201    real registers (A ... H), the memory-based registers (r8 ... r31)
2202    and the first NUM_STACK_LOCS words on the stack.  We use this to
2203    avoid generating redundant move instructions.
2204 
2205    A value in the range 0 .. 31 indicates register A .. r31.
2206    A value in the range 32 .. 63 indicates stack slot (value - 32).
2207    A value of NOT_KNOWN indicates that the contents of that location
2208    are not known.  */
2209 
2210 #define NUM_STACK_LOCS	32
2211 #define NOT_KNOWN       127
2212 
2213 static unsigned char content_memory [32 + NUM_STACK_LOCS];
2214 
2215 static unsigned char saved_update_index = NOT_KNOWN;
2216 static unsigned char saved_update_value;
2217 static machine_mode saved_update_mode;
2218 
2219 
2220 static inline void
2221 clear_content_memory (void)
2222 {
2223   memset (content_memory, NOT_KNOWN, sizeof content_memory);
2224   if (dump_file)
2225     fprintf (dump_file, "  clear content memory\n");
2226   saved_update_index = NOT_KNOWN;
2227 }
2228 
2229 /* Convert LOC into an index into the content_memory array.
2230    If LOC cannot be converted, return NOT_KNOWN.  */
2231 
2232 static unsigned char
2233 get_content_index (rtx loc)
2234 {
2235   machine_mode mode;
2236 
2237   if (loc == NULL_RTX)
2238     return NOT_KNOWN;
2239 
2240   if (REG_P (loc))
2241     {
2242       if (REGNO (loc) < 32)
2243 	return REGNO (loc);
2244       return NOT_KNOWN;
2245     }
2246 
2247   mode = GET_MODE (loc);
2248 
2249   if (! rl78_stack_based_mem (loc, mode))
2250     return NOT_KNOWN;
2251 
2252   loc = XEXP (loc, 0);
2253 
2254   if (REG_P (loc))
2255     /* loc = MEM (SP) */
2256     return 32;
2257 
2258   /* loc = MEM (PLUS (SP, INT)).  */
2259   loc = XEXP (loc, 1);
2260 
2261   if (INTVAL (loc) < NUM_STACK_LOCS)
2262     return 32 + INTVAL (loc);
2263 
2264   return NOT_KNOWN;
2265 }
2266 
2267 /* Return a string describing content INDEX in mode MODE.
2268    WARNING: Can return a pointer to a static buffer.  */
2269 static const char *
2270 get_content_name (unsigned char index, machine_mode mode)
2271 {
2272   static char buffer [128];
2273 
2274   if (index == NOT_KNOWN)
2275     return "Unknown";
2276 
2277   if (index > 31)
2278     sprintf (buffer, "stack slot %d", index - 32);
2279   else if (mode == HImode)
2280     sprintf (buffer, "%s%s",
2281 	     reg_names [index + 1], reg_names [index]);
2282   else
2283     return reg_names [index];
2284 
2285   return buffer;
2286 }
2287 
2288 #if DEBUG_ALLOC
2289 
2290 static void
2291 display_content_memory (FILE * file)
2292 {
2293   unsigned int i;
2294 
2295   fprintf (file, " Known memory contents:\n");
2296 
2297   for (i = 0; i < sizeof content_memory; i++)
2298     if (content_memory[i] != NOT_KNOWN)
2299       {
2300 	fprintf (file, "   %s contains a copy of ", get_content_name (i, QImode));
2301 	fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2302       }
2303 }
2304 #endif
2305 
2306 static void
2307 update_content (unsigned char index, unsigned char val, machine_mode mode)
2308 {
2309   unsigned int i;
2310 
2311   gcc_assert (index < sizeof content_memory);
2312 
2313   content_memory [index] = val;
2314   if (val != NOT_KNOWN)
2315     content_memory [val] = index;
2316 
2317   /* Make the entry in dump_file *before* VAL is increased below.  */
2318   if (dump_file)
2319     {
2320       fprintf (dump_file, "  %s now contains ", get_content_name (index, mode));
2321       if (val == NOT_KNOWN)
2322 	fprintf (dump_file, "Unknown\n");
2323       else
2324 	fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2325     }
2326 
2327   if (mode == HImode)
2328     {
2329       val = val == NOT_KNOWN ? val : val + 1;
2330 
2331       content_memory [index + 1] = val;
2332       if (val != NOT_KNOWN)
2333 	{
2334 	  content_memory [val] = index + 1;
2335 	  -- val;
2336 	}
2337     }
2338 
2339   /* Any other places that had INDEX recorded as their contents are now invalid.  */
2340   for (i = 0; i < sizeof content_memory; i++)
2341     {
2342       if (i == index
2343 	  || (val != NOT_KNOWN && i == val))
2344 	{
2345 	  if (mode == HImode)
2346 	    ++ i;
2347 	  continue;
2348 	}
2349 
2350       if (content_memory[i] == index
2351 	  || (val != NOT_KNOWN && content_memory[i] == val))
2352 	{
2353 	  content_memory[i] = NOT_KNOWN;
2354 
2355 	  if (dump_file)
2356 	    fprintf (dump_file, "  %s cleared\n", get_content_name (i, mode));
2357 
2358 	  if (mode == HImode)
2359 	    content_memory[++ i] = NOT_KNOWN;
2360 	}
2361     }
2362 }
2363 
2364 /* Record that LOC contains VALUE.
2365    For HImode locations record that LOC+1 contains VALUE+1.
2366    If LOC is not a register or stack slot, do nothing.
2367    If VALUE is not a register or stack slot, clear the recorded content.  */
2368 
2369 static void
2370 record_content (rtx loc, rtx value)
2371 {
2372   machine_mode mode;
2373   unsigned char index;
2374   unsigned char val;
2375 
2376   if ((index = get_content_index (loc)) == NOT_KNOWN)
2377     return;
2378 
2379   val = get_content_index (value);
2380 
2381   mode = GET_MODE (loc);
2382 
2383   if (val == index)
2384     {
2385       if (! optimize)
2386 	return;
2387 
2388       /* This should not happen when optimizing.  */
2389 #if 1
2390       fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2391 	       get_content_name (val, mode));
2392       return;
2393 #else
2394       gcc_unreachable ();
2395 #endif
2396     }
2397 
2398   update_content (index, val, mode);
2399 }
2400 
2401 /* Returns TRUE if LOC already contains a copy of VALUE.  */
2402 
2403 static bool
2404 already_contains (rtx loc, rtx value)
2405 {
2406   unsigned char index;
2407   unsigned char val;
2408 
2409   if ((index = get_content_index (loc)) == NOT_KNOWN)
2410     return false;
2411 
2412   if ((val = get_content_index (value)) == NOT_KNOWN)
2413     return false;
2414 
2415   if (content_memory [index] != val)
2416     return false;
2417 
2418   if (GET_MODE (loc) == HImode)
2419     return content_memory [index + 1] == val + 1;
2420 
2421   return true;
2422 }
2423 
2424 bool
2425 rl78_es_addr (rtx addr)
2426 {
2427   if (GET_CODE (addr) == MEM)
2428     addr = XEXP (addr, 0);
2429   if (GET_CODE (addr) != UNSPEC)
2430     return false;
2431   if (XINT (addr, 1) != UNS_ES_ADDR)
2432     return false;
2433   return true;
2434 }
2435 
2436 rtx
2437 rl78_es_base (rtx addr)
2438 {
2439   if (GET_CODE (addr) == MEM)
2440     addr = XEXP (addr, 0);
2441   addr = XVECEXP (addr, 0, 1);
2442   if (GET_CODE (addr) == CONST
2443       && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2444     addr = XEXP (XEXP (addr, 0), 0);
2445   /* Mode doesn't matter here.  */
2446   return gen_rtx_MEM (HImode, addr);
2447 }
2448 
2449 /* Rescans an insn to see if it's recognized again.  This is done
2450    carefully to ensure that all the constraint information is accurate
2451    for the newly matched insn.  */
2452 static bool
2453 insn_ok_now (rtx_insn * insn)
2454 {
2455   rtx pattern = PATTERN (insn);
2456   int i;
2457 
2458   INSN_CODE (insn) = -1;
2459 
2460   if (recog (pattern, insn, 0) > -1)
2461     {
2462       extract_insn (insn);
2463       if (constrain_operands (1, get_preferred_alternatives (insn)))
2464 	{
2465 #if DEBUG_ALLOC
2466 	  fprintf (stderr, "\033[32m");
2467 	  debug_rtx (insn);
2468 	  fprintf (stderr, "\033[0m");
2469 #endif
2470 	  if (SET_P (pattern))
2471 	    record_content (SET_DEST (pattern), SET_SRC (pattern));
2472 
2473 	  /* We need to detect far addresses that haven't been
2474 	     converted to es/lo16 format.  */
2475 	  for (i=0; i<recog_data.n_operands; i++)
2476 	    if (GET_CODE (OP (i)) == MEM
2477 		&& GET_MODE (XEXP (OP (i), 0)) == SImode
2478 		&& GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2479 	      return false;
2480 
2481 	  return true;
2482 	}
2483     }
2484   else
2485     {
2486       /* We need to re-recog the insn with virtual registers to get
2487 	 the operands.  */
2488       cfun->machine->virt_insns_ok = 1;
2489       if (recog (pattern, insn, 0) > -1)
2490 	{
2491 	  extract_insn (insn);
2492 	  if (constrain_operands (0, get_preferred_alternatives (insn)))
2493 	    {
2494 	      cfun->machine->virt_insns_ok = 0;
2495 	      return false;
2496 	    }
2497 	}
2498 
2499 #if DEBUG_ALLOC
2500       fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2501       debug_rtx (insn);
2502 #endif
2503       gcc_unreachable ();
2504     }
2505 
2506 #if DEBUG_ALLOC
2507   fprintf (stderr, "\033[31m");
2508   debug_rtx (insn);
2509   fprintf (stderr, "\033[0m");
2510 #endif
2511   return false;
2512 }
2513 
2514 #if DEBUG_ALLOC
2515 #define WORKED      fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2516 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2517 #define FAILED      fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2518 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2519 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2520 #else
2521 #define FAILED gcc_unreachable ()
2522 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2523 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2524 #endif
2525 
2526 /* Registers into which we move the contents of virtual registers.  */
2527 #define X gen_rtx_REG (QImode, X_REG)
2528 #define A gen_rtx_REG (QImode, A_REG)
2529 #define C gen_rtx_REG (QImode, C_REG)
2530 #define B gen_rtx_REG (QImode, B_REG)
2531 #define E gen_rtx_REG (QImode, E_REG)
2532 #define D gen_rtx_REG (QImode, D_REG)
2533 #define L gen_rtx_REG (QImode, L_REG)
2534 #define H gen_rtx_REG (QImode, H_REG)
2535 
2536 #define AX gen_rtx_REG (HImode, AX_REG)
2537 #define BC gen_rtx_REG (HImode, BC_REG)
2538 #define DE gen_rtx_REG (HImode, DE_REG)
2539 #define HL gen_rtx_REG (HImode, HL_REG)
2540 
2541 /* Returns TRUE if R is a virtual register.  */
2542 static inline bool
2543 is_virtual_register (rtx r)
2544 {
2545   return (GET_CODE (r) == REG
2546 	  && REGNO (r) >= 8
2547 	  && REGNO (r) < 32);
2548 }
2549 
2550 /* In all these alloc routines, we expect the following: the insn
2551    pattern is unshared, the insn was previously recognized and failed
2552    due to predicates or constraints, and the operand data is in
2553    recog_data.  */
2554 
2555 static int virt_insn_was_frame;
2556 
2557 /* Hook for all insns we emit.  Re-mark them as FRAME_RELATED if
2558    needed.  */
2559 static rtx
2560 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2561 {
2562 #if DEBUG_ALLOC
2563   fprintf (stderr, "\033[36m%d: ", line);
2564   debug_rtx (r);
2565   fprintf (stderr, "\033[0m");
2566 #endif
2567   /*SCHED_GROUP_P (r) = 1;*/
2568   if (virt_insn_was_frame)
2569     RTX_FRAME_RELATED_P (r) = 1;
2570   return r;
2571 }
2572 
2573 #define EM(x) EM2 (__LINE__, x)
2574 
2575 /* Return a suitable RTX for the low half of a __far address.  */
2576 static rtx
2577 rl78_lo16 (rtx addr)
2578 {
2579   rtx r;
2580 
2581   if (GET_CODE (addr) == SYMBOL_REF
2582       || GET_CODE (addr) == CONST)
2583     {
2584       r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2585       r = gen_rtx_CONST (HImode, r);
2586     }
2587   else
2588     r = rl78_subreg (HImode, addr, SImode, 0);
2589 
2590   r = gen_es_addr (r);
2591   cfun->machine->uses_es = true;
2592 
2593   return r;
2594 }
2595 
2596 /* Return a suitable RTX for the high half's lower byte of a __far address.  */
2597 static rtx
2598 rl78_hi8 (rtx addr)
2599 {
2600   if (GET_CODE (addr) == SYMBOL_REF
2601       || GET_CODE (addr) == CONST)
2602     {
2603       rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2604       r = gen_rtx_CONST (QImode, r);
2605       return r;
2606     }
2607   return rl78_subreg (QImode, addr, SImode, 2);
2608 }
2609 
2610 static void
2611 add_postponed_content_update (rtx to, rtx value)
2612 {
2613   unsigned char index;
2614 
2615   if ((index = get_content_index (to)) == NOT_KNOWN)
2616     return;
2617 
2618   gcc_assert (saved_update_index == NOT_KNOWN);
2619   saved_update_index = index;
2620   saved_update_value = get_content_index (value);
2621   saved_update_mode  = GET_MODE (to);
2622 }
2623 
2624 static void
2625 process_postponed_content_update (void)
2626 {
2627   if (saved_update_index != NOT_KNOWN)
2628     {
2629       update_content (saved_update_index, saved_update_value, saved_update_mode);
2630       saved_update_index = NOT_KNOWN;
2631     }
2632 }
2633 
2634 /* Generate and emit a move of (register) FROM into TO.  if WHERE is not NULL
2635    then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2636    after WHERE.  If TO already contains FROM then do nothing.  Returns TO if
2637    BEFORE is true, FROM otherwise.  */
2638 static rtx
2639 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2640 {
2641   machine_mode mode = GET_MODE (to);
2642 
2643   if (optimize && before && already_contains (to, from))
2644     {
2645 #if DEBUG_ALLOC
2646       display_content_memory (stderr);
2647 #endif
2648       if (dump_file)
2649 	{
2650 	  fprintf (dump_file, " Omit move of %s into ",
2651 		   get_content_name (get_content_index (from), mode));
2652 	  fprintf (dump_file, "%s as it already contains this value\n",
2653 		   get_content_name (get_content_index (to), mode));
2654 	}
2655     }
2656   else
2657     {
2658       rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2659 
2660       EM (move);
2661 
2662       if (where == NULL_RTX)
2663 	emit_insn (move);
2664       else if (before)
2665 	emit_insn_before (move, where);
2666       else
2667 	{
2668 	  rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2669 
2670 	  /* If necessary move REG_EH_REGION notes forward.
2671 	     cf. compiling gcc.dg/pr44545.c.  */
2672 	  if (note != NULL_RTX)
2673 	    {
2674 	      add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2675 	      remove_note (where, note);
2676 	    }
2677 
2678 	  emit_insn_after (move, where);
2679 	}
2680 
2681       if (before)
2682 	record_content (to, from);
2683       else
2684 	add_postponed_content_update (to, from);
2685     }
2686 
2687   return before ? to : from;
2688 }
2689 
2690 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2691    copy it into NEWBASE and return the updated MEM.  Otherwise just
2692    return M.  Any needed insns are emitted before BEFORE.  */
2693 static rtx
2694 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2695 {
2696   rtx base, index, addendr;
2697   int addend = 0;
2698   int need_es = 0;
2699 
2700   if (! MEM_P (m))
2701     return m;
2702 
2703   if (GET_MODE (XEXP (m, 0)) == SImode)
2704     {
2705       rtx new_m;
2706       rtx seg = rl78_hi8 (XEXP (m, 0));
2707 
2708       if (!TARGET_ES0)
2709 	{
2710           emit_insn_before (EM (gen_movqi (A, seg)), before);
2711           emit_insn_before (EM (gen_movqi_to_es (A)), before);
2712         }
2713 
2714       record_content (A, NULL_RTX);
2715 
2716       new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2717       MEM_COPY_ATTRIBUTES (new_m, m);
2718       m = new_m;
2719       need_es = 1;
2720     }
2721 
2722   characterize_address (XEXP (m, 0), & base, & index, & addendr);
2723   gcc_assert (index == NULL_RTX);
2724 
2725   if (base == NULL_RTX)
2726     return m;
2727 
2728   if (addendr && GET_CODE (addendr) == CONST_INT)
2729     addend = INTVAL (addendr);
2730 
2731   gcc_assert (REG_P (base));
2732   gcc_assert (REG_P (newbase));
2733 
2734   int limit = 256 - GET_MODE_SIZE (GET_MODE (m));
2735 
2736   if (REGNO (base) == SP_REG)
2737     {
2738       if (addend >= 0 && addend <= limit)
2739 	return m;
2740     }
2741 
2742   /* BASE should be a virtual register.  We copy it to NEWBASE.  If
2743      the addend is out of range for DE/HL, we use AX to compute the full
2744      address.  */
2745 
2746   if (addend < 0
2747       || (addend > limit && REGNO (newbase) != BC_REG)
2748       || (addendr
2749 	  && (GET_CODE (addendr) != CONST_INT)
2750 	  && ((REGNO (newbase) != BC_REG))
2751 	  ))
2752     {
2753       /* mov ax, vreg
2754 	 add ax, #imm
2755 	 mov hl, ax	*/
2756       EM (emit_insn_before (gen_movhi (AX, base), before));
2757       EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2758       EM (emit_insn_before (gen_movhi (newbase, AX), before));
2759       record_content (AX, NULL_RTX);
2760       record_content (newbase, NULL_RTX);
2761 
2762       base = newbase;
2763       addend = 0;
2764       addendr = 0;
2765     }
2766   else
2767     {
2768       base = gen_and_emit_move (newbase, base, before, true);
2769     }
2770 
2771   if (addend)
2772     {
2773       record_content (base, NULL_RTX);
2774       base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2775     }
2776   else if (addendr)
2777     {
2778       record_content (base, NULL_RTX);
2779       base = gen_rtx_PLUS (HImode, base, addendr);
2780     }
2781 
2782   if (need_es)
2783     {
2784       m = change_address (m, GET_MODE (m), gen_es_addr (base));
2785       cfun->machine->uses_es = true;
2786     }
2787   else
2788     m = change_address (m, GET_MODE (m), base);
2789   return m;
2790 }
2791 
2792 /* Copy SRC to accumulator (A or AX), placing any generated insns
2793    before BEFORE.  Returns accumulator RTX.  */
2794 static rtx
2795 move_to_acc (int opno, rtx before)
2796 {
2797   rtx src = OP (opno);
2798   machine_mode mode = GET_MODE (src);
2799 
2800   if (REG_P (src) && REGNO (src) < 2)
2801     return src;
2802 
2803   if (mode == VOIDmode)
2804     mode = recog_data.operand_mode[opno];
2805 
2806   return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2807 }
2808 
2809 static void
2810 force_into_acc (rtx src, rtx before)
2811 {
2812   machine_mode mode = GET_MODE (src);
2813   rtx move;
2814 
2815   if (REG_P (src) && REGNO (src) < 2)
2816     return;
2817 
2818   move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2819 
2820   EM (move);
2821 
2822   emit_insn_before (move, before);
2823   record_content (AX, NULL_RTX);
2824 }
2825 
2826 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2827    after AFTER.  Returns accumulator RTX.  */
2828 static rtx
2829 move_from_acc (unsigned int opno, rtx after)
2830 {
2831   rtx dest = OP (opno);
2832   machine_mode mode = GET_MODE (dest);
2833 
2834   if (REG_P (dest) && REGNO (dest) < 2)
2835     return dest;
2836 
2837   return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2838 }
2839 
2840 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2841    before BEFORE.  Returns reg RTX.  */
2842 static rtx
2843 move_acc_to_reg (rtx acc, int regno, rtx before)
2844 {
2845   machine_mode mode = GET_MODE (acc);
2846   rtx reg;
2847 
2848   reg = gen_rtx_REG (mode, regno);
2849 
2850   return gen_and_emit_move (reg, acc, before, true);
2851 }
2852 
2853 /* Copy SRC to X, placing any generated insns before BEFORE.
2854    Returns X RTX.  */
2855 static rtx
2856 move_to_x (int opno, rtx before)
2857 {
2858   rtx src = OP (opno);
2859   machine_mode mode = GET_MODE (src);
2860   rtx reg;
2861 
2862   if (mode == VOIDmode)
2863     mode = recog_data.operand_mode[opno];
2864   reg = (mode == QImode) ? X : AX;
2865 
2866   if (mode == QImode || ! is_virtual_register (OP (opno)))
2867     {
2868       OP (opno) = move_to_acc (opno, before);
2869       OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
2870       return reg;
2871     }
2872 
2873   return gen_and_emit_move (reg, src, before, true);
2874 }
2875 
2876 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2877    Returns H/HL RTX.  */
2878 static rtx
2879 move_to_hl (int opno, rtx before)
2880 {
2881   rtx src = OP (opno);
2882   machine_mode mode = GET_MODE (src);
2883   rtx reg;
2884 
2885   if (mode == VOIDmode)
2886     mode = recog_data.operand_mode[opno];
2887   reg = (mode == QImode) ? L : HL;
2888 
2889   if (mode == QImode || ! is_virtual_register (OP (opno)))
2890     {
2891       OP (opno) = move_to_acc (opno, before);
2892       OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2893       return reg;
2894     }
2895 
2896   return gen_and_emit_move (reg, src, before, true);
2897 }
2898 
2899 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2900    Returns E/DE RTX.  */
2901 static rtx
2902 move_to_de (int opno, rtx before)
2903 {
2904   rtx src = OP (opno);
2905   machine_mode mode = GET_MODE (src);
2906   rtx reg;
2907 
2908   if (mode == VOIDmode)
2909     mode = recog_data.operand_mode[opno];
2910 
2911   reg = (mode == QImode) ? E : DE;
2912 
2913   if (mode == QImode || ! is_virtual_register (OP (opno)))
2914     {
2915       OP (opno) = move_to_acc (opno, before);
2916       OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2917     }
2918   else
2919     {
2920       gen_and_emit_move (reg, src, before, true);
2921     }
2922 
2923   return reg;
2924 }
2925 
2926 /* Devirtualize an insn of the form (SET (op) (unop (op))).  */
2927 static void
2928 rl78_alloc_physical_registers_op1 (rtx_insn * insn)
2929 {
2930   /* op[0] = func op[1] */
2931 
2932   /* We first try using A as the destination, then copying it
2933      back.  */
2934   if (rtx_equal_p (OP (0), OP (1)))
2935     {
2936       OP (0) =
2937       OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2938     }
2939   else
2940     {
2941       /* If necessary, load the operands into BC and HL.
2942 	 Check to see if we already have OP (0) in HL
2943 	 and if so, swap the order.
2944 
2945 	 It is tempting to perform this optimization when OP(0) does
2946 	 not hold a MEM, but this leads to bigger code in general.
2947 	 The problem is that if OP(1) holds a MEM then swapping it
2948 	 into BC means a BC-relative load is used and these are 3
2949 	 bytes long vs 1 byte for an HL load.  */
2950       if (MEM_P (OP (0))
2951 	  && already_contains (HL, XEXP (OP (0), 0)))
2952 	{
2953 	  OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2954 	  OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2955 	}
2956       else
2957 	{
2958 	  OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2959 	  OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2960 	}
2961     }
2962 
2963   MAYBE_OK (insn);
2964 
2965   OP (0) = move_from_acc (0, insn);
2966 
2967   MAYBE_OK (insn);
2968 
2969   /* Try copying the src to acc first, then.  This is for, for
2970      example, ZERO_EXTEND or NOT.  */
2971   OP (1) = move_to_acc (1, insn);
2972 
2973   MUST_BE_OK (insn);
2974 }
2975 
2976 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2977    Assumes that the current insn has already been recognised and hence the
2978    constraint data has been filled in.  */
2979 static bool
2980 has_constraint (unsigned int opnum, enum constraint_num constraint)
2981 {
2982   const char * p = recog_data.constraints[opnum];
2983 
2984   /* No constraints means anything is accepted.  */
2985   if (p == NULL || *p == 0 || *p == ',')
2986     return true;
2987 
2988   do
2989     {
2990       char c;
2991       unsigned int len;
2992 
2993       c = *p;
2994       len = CONSTRAINT_LEN (c, p);
2995       gcc_assert (len > 0);
2996 
2997       switch (c)
2998 	{
2999 	case 0:
3000 	case ',':
3001 	  return false;
3002 	default:
3003 	  if (lookup_constraint (p) == constraint)
3004 	    return true;
3005 	}
3006       p += len;
3007     }
3008   while (1);
3009 }
3010 
3011 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))).  */
3012 static void
3013 rl78_alloc_physical_registers_op2 (rtx_insn * insn)
3014 {
3015   rtx prev;
3016   rtx first;
3017   bool hl_used;
3018   int tmp_id;
3019   rtx saved_op1;
3020 
3021   if (rtx_equal_p (OP (0), OP (1)))
3022     {
3023       if (MEM_P (OP (2)))
3024 	{
3025 	  OP (0) =
3026 	  OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3027 	  OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3028 	}
3029       else
3030 	{
3031 	  OP (0) =
3032 	  OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3033 	  OP (2) = transcode_memory_rtx (OP (2), DE, insn);
3034 	}
3035     }
3036   else if (rtx_equal_p (OP (0), OP (2)))
3037     {
3038       OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3039       OP (0) =
3040       OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3041     }
3042   else
3043     {
3044       OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3045       OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3046       OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3047     }
3048 
3049   MAYBE_OK (insn);
3050 
3051   prev = prev_nonnote_nondebug_insn (insn);
3052   if (recog_data.constraints[1][0] == '%'
3053       && is_virtual_register (OP (1))
3054       && ! is_virtual_register (OP (2))
3055       && ! CONSTANT_P (OP (2)))
3056     {
3057       rtx tmp = OP (1);
3058       OP (1) = OP (2);
3059       OP (2) = tmp;
3060     }
3061 
3062   /* Make a note of whether (H)L is being used.  It matters
3063      because if OP (2) also needs reloading, then we must take
3064      care not to corrupt HL.  */
3065   hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
3066 
3067   /* If HL is not currently being used and dest == op1 then there are
3068      some possible optimizations available by reloading one of the
3069      operands into HL, before trying to use the accumulator.  */
3070   if (optimize
3071       && ! hl_used
3072       && rtx_equal_p (OP (0), OP (1)))
3073     {
3074       /* If op0 is a Ws1 type memory address then switching the base
3075 	 address register to HL might allow us to perform an in-memory
3076 	 operation.  (eg for the INCW instruction).
3077 
3078 	 FIXME: Adding the move into HL is costly if this optimization is not
3079 	 going to work, so for now, make sure that we know that the new insn will
3080 	 match the requirements of the addhi3_real pattern.  Really we ought to
3081 	 generate a candidate sequence, test that, and then install it if the
3082 	 results are good.  */
3083       if (satisfies_constraint_Ws1 (OP (0))
3084 	  && has_constraint (0, CONSTRAINT_Wh1)
3085 	  && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3086 	{
3087 	  rtx base, index, addend, newbase;
3088 
3089 	  characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
3090 	  gcc_assert (index == NULL_RTX);
3091 	  gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3092 
3093 	  /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset.  */
3094 	  if (addend != NULL_RTX)
3095 	    {
3096 	      newbase = gen_and_emit_move (HL, base, insn, true);
3097 	      record_content (newbase, NULL_RTX);
3098 	      newbase = gen_rtx_PLUS (HImode, newbase, addend);
3099 
3100 	      OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
3101 
3102 	      /* We do not want to fail here as this means that
3103 		 we have inserted useless insns into the stream.  */
3104 	      MUST_BE_OK (insn);
3105 	    }
3106 	}
3107       else if (REG_P (OP (0))
3108 	       && satisfies_constraint_Ws1 (OP (2))
3109 	       && has_constraint (2, CONSTRAINT_Wh1))
3110 	{
3111 	  rtx base, index, addend, newbase;
3112 
3113 	  characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
3114 	  gcc_assert (index == NULL_RTX);
3115 	  gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3116 
3117 	  /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset.  */
3118 	  if (addend != NULL_RTX)
3119 	    {
3120 	      gen_and_emit_move (HL, base, insn, true);
3121 
3122 	      if (REGNO (OP (0)) != X_REG)
3123 		{
3124 		  OP (1) = move_to_acc (1, insn);
3125 		  OP (0) = move_from_acc (0, insn);
3126 		}
3127 
3128 	      record_content (HL, NULL_RTX);
3129 	      newbase = gen_rtx_PLUS (HImode, HL, addend);
3130 
3131 	      OP (2) = change_address (OP (2), VOIDmode, newbase);
3132 
3133 	      /* We do not want to fail here as this means that
3134 		 we have inserted useless insns into the stream.  */
3135 	      MUST_BE_OK (insn);
3136 	    }
3137 	}
3138     }
3139 
3140   OP (0) = move_from_acc (0, insn);
3141 
3142   tmp_id = get_max_insn_count ();
3143   saved_op1 = OP (1);
3144 
3145   if (rtx_equal_p (OP (1), OP (2)))
3146     OP (2) = OP (1) = move_to_acc (1, insn);
3147   else
3148     OP (1) = move_to_acc (1, insn);
3149 
3150   MAYBE_OK (insn);
3151 
3152   /* If we omitted the move of OP1 into the accumulator (because
3153      it was already there from a previous insn), then force the
3154      generation of the move instruction now.  We know that we
3155      are about to emit a move into HL (or DE) via AX, and hence
3156      our optimization to remove the load of OP1 is no longer valid.  */
3157   if (tmp_id == get_max_insn_count ())
3158     force_into_acc (saved_op1, insn);
3159 
3160   /* We have to copy op2 to HL (or DE), but that involves AX, which
3161      already has a live value.  Emit it before those insns.  */
3162 
3163   if (prev)
3164     first = next_nonnote_nondebug_insn (prev);
3165   else
3166     for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3167       ;
3168 
3169   OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
3170 
3171   MUST_BE_OK (insn);
3172 }
3173 
3174 /* Devirtualize an insn of the form SET (PC) (MEM/REG).  */
3175 static void
3176 rl78_alloc_physical_registers_ro1 (rtx_insn * insn)
3177 {
3178   OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3179 
3180   MAYBE_OK (insn);
3181 
3182   OP (0) = move_to_acc (0, insn);
3183 
3184   MUST_BE_OK (insn);
3185 }
3186 
3187 /* Devirtualize a compare insn.  */
3188 static void
3189 rl78_alloc_physical_registers_cmp (rtx_insn * insn)
3190 {
3191   int tmp_id;
3192   rtx saved_op1;
3193   rtx prev = prev_nonnote_nondebug_insn (insn);
3194   rtx first;
3195 
3196   OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3197   OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3198 
3199   /* HI compares have to have OP (1) in AX, but QI
3200      compares do not, so it is worth checking here.  */
3201   MAYBE_OK (insn);
3202 
3203   /* For an HImode compare, OP (1) must always be in AX.
3204      But if OP (1) is a REG (and not AX), then we can avoid
3205      a reload of OP (1) if we reload OP (2) into AX and invert
3206      the comparison.  */
3207   if (REG_P (OP (1))
3208       && REGNO (OP (1)) != AX_REG
3209       && GET_MODE (OP (1)) == HImode
3210       && MEM_P (OP (2)))
3211     {
3212       rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
3213 
3214       OP (2) = move_to_acc (2, insn);
3215 
3216       switch (GET_CODE (cmp))
3217 	{
3218 	case EQ:
3219 	case NE:
3220 	  break;
3221 	case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
3222 	case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
3223 	case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
3224 	case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
3225 
3226 	case LT:
3227 	case GT:
3228 	case LE:
3229 	case GE:
3230 #if DEBUG_ALLOC
3231 	  debug_rtx (insn);
3232 #endif
3233 	default:
3234 	  gcc_unreachable ();
3235 	}
3236 
3237       if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
3238 	PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
3239       else
3240 	PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
3241 
3242       MUST_BE_OK (insn);
3243     }
3244 
3245   /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3246      should be handled by the second alternative of the cbranchhi_real pattern.  */
3247   if (rtx_equal_p (OP (1), OP (2)))
3248     {
3249       OP (1) = OP (2) = BC;
3250       MUST_BE_OK (insn);
3251     }
3252 
3253   tmp_id = get_max_insn_count ();
3254   saved_op1 = OP (1);
3255 
3256   OP (1) = move_to_acc (1, insn);
3257 
3258   MAYBE_OK (insn);
3259 
3260   /* If we omitted the move of OP1 into the accumulator (because
3261      it was already there from a previous insn), then force the
3262      generation of the move instruction now.  We know that we
3263      are about to emit a move into HL via AX, and hence our
3264      optimization to remove the load of OP1 is no longer valid.  */
3265   if (tmp_id == get_max_insn_count ())
3266     force_into_acc (saved_op1, insn);
3267 
3268   /* We have to copy op2 to HL, but that involves the acc, which
3269      already has a live value.  Emit it before those insns.  */
3270   if (prev)
3271     first = next_nonnote_nondebug_insn (prev);
3272   else
3273     for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3274       ;
3275   OP (2) = move_to_hl (2, first);
3276 
3277   MUST_BE_OK (insn);
3278 }
3279 
3280 /* Like op2, but AX = A * X.  */
3281 static void
3282 rl78_alloc_physical_registers_umul (rtx_insn * insn)
3283 {
3284   rtx prev = prev_nonnote_nondebug_insn (insn);
3285   rtx first;
3286   int tmp_id;
3287   rtx saved_op1;
3288 
3289   OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3290   OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3291   OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3292 
3293   MAYBE_OK (insn);
3294 
3295   if (recog_data.constraints[1][0] == '%'
3296       && is_virtual_register (OP (1))
3297       && !is_virtual_register (OP (2))
3298       && !CONSTANT_P (OP (2)))
3299     {
3300       rtx tmp = OP (1);
3301       OP (1) = OP (2);
3302       OP (2) = tmp;
3303     }
3304 
3305   OP (0) = move_from_acc (0, insn);
3306 
3307   tmp_id = get_max_insn_count ();
3308   saved_op1 = OP (1);
3309 
3310   if (rtx_equal_p (OP (1), OP (2)))
3311     {
3312       gcc_assert (GET_MODE (OP (2)) == QImode);
3313       /* The MULU instruction does not support duplicate arguments
3314 	 but we know that if we copy OP (2) to X it will do so via
3315 	 A and thus OP (1) will already be loaded into A.  */
3316       OP (2) = move_to_x (2, insn);
3317       OP (1) = A;
3318     }
3319   else
3320     OP (1) = move_to_acc (1, insn);
3321 
3322   MAYBE_OK (insn);
3323 
3324   /* If we omitted the move of OP1 into the accumulator (because
3325      it was already there from a previous insn), then force the
3326      generation of the move instruction now.  We know that we
3327      are about to emit a move into HL (or DE) via AX, and hence
3328      our optimization to remove the load of OP1 is no longer valid.  */
3329   if (tmp_id == get_max_insn_count ())
3330     force_into_acc (saved_op1, insn);
3331 
3332   /* We have to copy op2 to X, but that involves the acc, which
3333      already has a live value.  Emit it before those insns.  */
3334 
3335   if (prev)
3336     first = next_nonnote_nondebug_insn (prev);
3337   else
3338     for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3339       ;
3340   OP (2) = move_to_x (2, first);
3341 
3342   MUST_BE_OK (insn);
3343 }
3344 
3345 static void
3346 rl78_alloc_address_registers_macax (rtx_insn * insn)
3347 {
3348   int which, op;
3349   bool replace_in_op0 = false;
3350   bool replace_in_op1 = false;
3351 
3352   MAYBE_OK (insn);
3353 
3354   /* Two different MEMs are not allowed.  */
3355   which = 0;
3356   for (op = 2; op >= 0; op --)
3357     {
3358       if (MEM_P (OP (op)))
3359 	{
3360 	  if (op == 0 && replace_in_op0)
3361 	    continue;
3362 	  if (op == 1 && replace_in_op1)
3363 	    continue;
3364 
3365 	  switch (which)
3366 	    {
3367 	    case 0:
3368 	      /* If we replace a MEM, make sure that we replace it for all
3369 		 occurrences of the same MEM in the insn.  */
3370 	      replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3371 	      replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3372 
3373 	      OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3374 	      if (op == 2
3375 		  && MEM_P (OP (op))
3376 		  && ((GET_CODE (XEXP (OP (op), 0)) == REG
3377 		       && REGNO (XEXP (OP (op), 0)) == SP_REG)
3378 		      || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3379 			  && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3380 		{
3381 		  emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3382 		  OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3383 		}
3384 	      if (replace_in_op0)
3385 		OP (0) = OP (op);
3386 	      if (replace_in_op1)
3387 		OP (1) = OP (op);
3388 	      break;
3389 	    case 1:
3390 	      OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3391 	      break;
3392 	    case 2:
3393 	      OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3394 	      break;
3395 	    }
3396 	  which ++;
3397 	}
3398     }
3399 
3400   MUST_BE_OK (insn);
3401 }
3402 
3403 static void
3404 rl78_alloc_address_registers_div (rtx_insn * insn)
3405 {
3406   MUST_BE_OK (insn);
3407 }
3408 
3409 /* Scan all insns and devirtualize them.  */
3410 static void
3411 rl78_alloc_physical_registers (void)
3412 {
3413   /* During most of the compile, gcc is dealing with virtual
3414      registers.  At this point, we need to assign physical registers
3415      to the vitual ones, and copy in/out as needed.  */
3416 
3417   rtx_insn *insn, *curr;
3418   enum attr_valloc valloc_method;
3419 
3420   for (insn = get_insns (); insn; insn = curr)
3421     {
3422       int i;
3423 
3424       curr = next_nonnote_nondebug_insn (insn);
3425 
3426       if (INSN_P (insn)
3427 	  && (GET_CODE (PATTERN (insn)) == SET
3428 	      || GET_CODE (PATTERN (insn)) == CALL)
3429 	  && INSN_CODE (insn) == -1)
3430 	{
3431 	  if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3432 	    continue;
3433 	  i = recog (PATTERN (insn), insn, 0);
3434 	  if (i == -1)
3435 	    {
3436 	      debug_rtx (insn);
3437 	      gcc_unreachable ();
3438 	    }
3439 	  INSN_CODE (insn) = i;
3440 	}
3441     }
3442 
3443   cfun->machine->virt_insns_ok = 0;
3444   cfun->machine->real_insns_ok = 1;
3445 
3446   clear_content_memory ();
3447 
3448   for (insn = get_insns (); insn; insn = curr)
3449     {
3450       rtx pattern;
3451 
3452       curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3453 
3454       if (!INSN_P (insn))
3455 	{
3456 	  if (LABEL_P (insn))
3457 	    clear_content_memory ();
3458 
3459  	  continue;
3460 	}
3461 
3462       if (dump_file)
3463 	fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3464 
3465       pattern = PATTERN (insn);
3466       if (GET_CODE (pattern) == PARALLEL)
3467 	pattern = XVECEXP (pattern, 0, 0);
3468       if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3469 	clear_content_memory ();
3470       if (GET_CODE (pattern) != SET
3471 	  && GET_CODE (pattern) != CALL)
3472 	continue;
3473       if (GET_CODE (pattern) == SET
3474 	  && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3475 	continue;
3476 
3477       valloc_method = get_attr_valloc (insn);
3478 
3479       PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3480 
3481       if (valloc_method == VALLOC_MACAX)
3482 	{
3483 	  record_content (AX, NULL_RTX);
3484 	  record_content (BC, NULL_RTX);
3485 	  record_content (DE, NULL_RTX);
3486 	}
3487 
3488       if (insn_ok_now (insn))
3489 	continue;
3490 
3491       INSN_CODE (insn) = -1;
3492 
3493       if (RTX_FRAME_RELATED_P (insn))
3494 	virt_insn_was_frame = 1;
3495       else
3496 	virt_insn_was_frame = 0;
3497 
3498       switch (valloc_method)
3499 	{
3500 	case VALLOC_OP1:
3501 	  rl78_alloc_physical_registers_op1 (insn);
3502 	  break;
3503 	case VALLOC_OP2:
3504 	  rl78_alloc_physical_registers_op2 (insn);
3505 	  break;
3506 	case VALLOC_RO1:
3507 	  rl78_alloc_physical_registers_ro1 (insn);
3508 	  break;
3509 	case VALLOC_CMP:
3510 	  rl78_alloc_physical_registers_cmp (insn);
3511 	  break;
3512 	case VALLOC_UMUL:
3513 	  rl78_alloc_physical_registers_umul (insn);
3514 	  break;
3515 	case VALLOC_MACAX:
3516 	  /* Macro that clobbers AX.  */
3517 	  rl78_alloc_address_registers_macax (insn);
3518 	  record_content (AX, NULL_RTX);
3519 	  record_content (BC, NULL_RTX);
3520 	  record_content (DE, NULL_RTX);
3521 	  break;
3522 	default:
3523 	  gcc_unreachable ();
3524 	}
3525 
3526       if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3527 	clear_content_memory ();
3528       else
3529 	process_postponed_content_update ();
3530     }
3531 
3532 #if DEBUG_ALLOC
3533   fprintf (stderr, "\033[0m");
3534 #endif
3535 }
3536 
3537 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3538    This function scans for uses of registers; the last use (i.e. first
3539    encounter when scanning backwards) triggers a REG_DEAD note if the
3540    reg was previously in DEAD[].  */
3541 static void
3542 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3543 {
3544   const char *fmt;
3545   int i, r;
3546   enum rtx_code code;
3547 
3548   if (!s)
3549     return;
3550 
3551   code = GET_CODE (s);
3552 
3553   switch (code)
3554     {
3555       /* Compare registers by number.  */
3556     case REG:
3557       r = REGNO (s);
3558       if (dump_file)
3559 	{
3560 	  fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3561 		   r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3562 	  print_rtl_single (dump_file, s);
3563 	}
3564       if (dead [r])
3565 	add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3566       for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3567 	dead [r + i] = 0;
3568       return;
3569 
3570       /* These codes have no constituent expressions
3571 	 and are unique.  */
3572     case SCRATCH:
3573     case CC0:
3574     case PC:
3575       return;
3576 
3577     case CONST_INT:
3578     case CONST_VECTOR:
3579     case CONST_DOUBLE:
3580     case CONST_FIXED:
3581       /* These are kept unique for a given value.  */
3582       return;
3583 
3584     default:
3585       break;
3586     }
3587 
3588   fmt = GET_RTX_FORMAT (code);
3589 
3590   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3591     {
3592       if (fmt[i] == 'E')
3593 	{
3594 	  int j;
3595 	  for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3596 	    rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3597 	}
3598       else if (fmt[i] == 'e')
3599 	rl78_note_reg_uses (dead, XEXP (s, i), insn);
3600     }
3601 }
3602 
3603 /* Like the previous function, but scan for SETs instead.  */
3604 static void
3605 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3606 {
3607   int r, i;
3608 
3609   if (GET_CODE (d) == MEM)
3610     rl78_note_reg_uses (dead, XEXP (d, 0), insn);
3611 
3612   if (GET_CODE (d) != REG)
3613     return;
3614 
3615   r = REGNO (d);
3616   if (dead [r])
3617     add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3618   if (dump_file)
3619     fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3620   for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3621     dead [r + i] = 1;
3622 }
3623 
3624 /* This is a rather crude register death pass.  Death status is reset
3625    at every jump or call insn.  */
3626 static void
3627 rl78_calculate_death_notes (void)
3628 {
3629   char dead[FIRST_PSEUDO_REGISTER];
3630   rtx insn, p, s, d;
3631   int i;
3632 
3633   memset (dead, 0, sizeof (dead));
3634 
3635   for (insn = get_last_insn ();
3636        insn;
3637        insn = prev_nonnote_nondebug_insn (insn))
3638     {
3639       if (dump_file)
3640 	{
3641 	  fprintf (dump_file, "\n--------------------------------------------------");
3642 	  fprintf (dump_file, "\nDead:");
3643 	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3644 	    if (dead[i])
3645 	      fprintf (dump_file, " %s", reg_names[i]);
3646 	  fprintf (dump_file, "\n");
3647 	  print_rtl_single (dump_file, insn);
3648 	}
3649 
3650       switch (GET_CODE (insn))
3651 	{
3652 	case INSN:
3653 	  p = PATTERN (insn);
3654 	  if (GET_CODE (p) == PARALLEL)
3655 	    {
3656 	      rtx q = XVECEXP (p, 0 ,1);
3657 
3658 	      /* This happens with the DIV patterns.  */
3659 	      if (GET_CODE (q) == SET)
3660 		{
3661 		  s = SET_SRC (q);
3662 		  d = SET_DEST (q);
3663 		  rl78_note_reg_set (dead, d, insn);
3664 		  rl78_note_reg_uses (dead, s, insn);
3665 
3666 		}
3667 	      p = XVECEXP (p, 0, 0);
3668 	    }
3669 
3670 	  switch (GET_CODE (p))
3671 	    {
3672 	    case SET:
3673 	      s = SET_SRC (p);
3674 	      d = SET_DEST (p);
3675 	      rl78_note_reg_set (dead, d, insn);
3676 	      rl78_note_reg_uses (dead, s, insn);
3677 	      break;
3678 
3679 	    case USE:
3680 	      rl78_note_reg_uses (dead, p, insn);
3681 	      break;
3682 
3683 	    default:
3684 	      break;
3685 	    }
3686 	  break;
3687 
3688 	case JUMP_INSN:
3689 	  if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3690 	    {
3691 	      memset (dead, 1, sizeof (dead));
3692 	      /* We expect a USE just prior to this, which will mark
3693 		 the actual return registers.  The USE will have a
3694 		 death note, but we aren't going to be modifying it
3695 		 after this pass.  */
3696 	      break;
3697 	    }
3698 	case CALL_INSN:
3699 	  memset (dead, 0, sizeof (dead));
3700 	  break;
3701 
3702 	default:
3703 	  break;
3704 	}
3705       if (dump_file)
3706 	print_rtl_single (dump_file, insn);
3707     }
3708 }
3709 
3710 /* Helper function to reset the origins in RP and the age in AGE for
3711    all registers.  */
3712 static void
3713 reset_origins (int *rp, int *age)
3714 {
3715   int i;
3716   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3717     {
3718       rp[i] = i;
3719       age[i] = 0;
3720     }
3721 }
3722 
3723 static void
3724 set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
3725 {
3726   rtx src = SET_SRC (pat);
3727   rtx dest = SET_DEST (pat);
3728   int mb = GET_MODE_SIZE (GET_MODE (dest));
3729   int i;
3730 
3731   if (GET_CODE (dest) == REG)
3732     {
3733       int dr = REGNO (dest);
3734 
3735       if (GET_CODE (src) == REG)
3736 	{
3737 	  int sr = REGNO (src);
3738 	  bool same = true;
3739 	  int best_age, best_reg;
3740 
3741 	  /* See if the copy is not needed.  */
3742 	  for (i = 0; i < mb; i ++)
3743 	    if (origins[dr + i] != origins[sr + i])
3744 	      same = false;
3745 
3746 	  if (same)
3747 	    {
3748 	      if (dump_file)
3749 		fprintf (dump_file, "deleting because dest already has correct value\n");
3750 	      delete_insn (insn);
3751 	      return;
3752 	    }
3753 
3754 	  if (dr < 8 || sr >= 8)
3755 	    {
3756 	      int ar;
3757 
3758 	      best_age = -1;
3759 	      best_reg = -1;
3760 
3761 	      /* See if the copy can be made from another
3762 		 bank 0 register instead, instead of the
3763 		 virtual src register.  */
3764 	      for (ar = 0; ar < 8; ar += mb)
3765 		{
3766 		  same = true;
3767 
3768 		  for (i = 0; i < mb; i ++)
3769 		    if (origins[ar + i] != origins[sr + i])
3770 		      same = false;
3771 
3772 		  /* The chip has some reg-reg move limitations.  */
3773 		  if (mb == 1 && dr > 3)
3774 		    same = false;
3775 
3776 		  if (same)
3777 		    {
3778 		      if (best_age == -1 || best_age > age[sr + i])
3779 			{
3780 			  best_age = age[sr + i];
3781 			  best_reg = sr;
3782 			}
3783 		    }
3784 		}
3785 
3786 	      if (best_reg != -1)
3787 		{
3788 		  /* FIXME: copy debug info too.  */
3789 		  SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3790 		  sr = best_reg;
3791 		}
3792 	    }
3793 
3794 	  for (i = 0; i < mb; i++)
3795 	    {
3796 	      origins[dr + i] = origins[sr + i];
3797 	      age[dr + i] = age[sr + i] + 1;
3798 	    }
3799 	}
3800       else
3801 	{
3802 	  /* The destination is computed, its origin is itself.  */
3803 	  if (dump_file)
3804 	    fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3805 		     dr, mb, mb == 1 ? "" : "s");
3806 
3807 	  for (i = 0; i < mb; i ++)
3808 	    {
3809 	      origins[dr + i] = dr + i;
3810 	      age[dr + i] = 0;
3811 	    }
3812 	}
3813 
3814       /* Any registers marked with that reg as an origin are reset.  */
3815       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3816 	if (origins[i] >= dr && origins[i] < dr + mb)
3817 	  {
3818 	    origins[i] = i;
3819 	    age[i] = 0;
3820 	  }
3821     }
3822 
3823   /* Special case - our MUL patterns uses AX and sometimes BC.  */
3824   if (get_attr_valloc (insn) == VALLOC_MACAX)
3825     {
3826       if (dump_file)
3827 	fprintf (dump_file, "Resetting origin of AX/BC for MUL pattern.\n");
3828 
3829       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3830 	if (i <= 3 || origins[i] <= 3)
3831 	  {
3832 	    origins[i] = i;
3833 	    age[i] = 0;
3834 	  }
3835     }
3836 
3837   if (GET_CODE (src) == ASHIFT
3838       || GET_CODE (src) == ASHIFTRT
3839       || GET_CODE (src) == LSHIFTRT)
3840     {
3841       rtx count = XEXP (src, 1);
3842 
3843       if (GET_CODE (count) == REG)
3844 	{
3845 	  /* Special case - our pattern clobbers the count register.  */
3846 	  int r = REGNO (count);
3847 
3848 	  if (dump_file)
3849 	    fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3850 
3851 	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3852 	    if (i == r || origins[i] == r)
3853 	      {
3854 		origins[i] = i;
3855 		age[i] = 0;
3856 	      }
3857 	}
3858     }
3859 }
3860 
3861 /* The idea behind this optimization is to look for cases where we
3862    move data from A to B to C, and instead move from A to B, and A to
3863    C.  If B is a virtual register or memory, this is a big win on its
3864    own.  If B turns out to be unneeded after this, it's a bigger win.
3865    For each register, we try to determine where it's value originally
3866    came from, if it's propogated purely through moves (and not
3867    computes).  The ORIGINS[] array has the regno for the "origin" of
3868    the value in the [regno] it's indexed by.  */
3869 static void
3870 rl78_propogate_register_origins (void)
3871 {
3872   int origins[FIRST_PSEUDO_REGISTER];
3873   int age[FIRST_PSEUDO_REGISTER];
3874   int i;
3875   rtx_insn *insn, *ninsn = NULL;
3876   rtx pat;
3877 
3878   reset_origins (origins, age);
3879 
3880   for (insn = get_insns (); insn; insn = ninsn)
3881     {
3882       ninsn = next_nonnote_nondebug_insn (insn);
3883 
3884       if (dump_file)
3885 	{
3886 	  fprintf (dump_file, "\n");
3887 	  fprintf (dump_file, "Origins:");
3888 	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3889 	    if (origins[i] != i)
3890 	      fprintf (dump_file, " r%d=r%d", i, origins[i]);
3891 	  fprintf (dump_file, "\n");
3892 	  print_rtl_single (dump_file, insn);
3893 	}
3894 
3895       switch (GET_CODE (insn))
3896 	{
3897 	case CODE_LABEL:
3898 	case BARRIER:
3899 	case CALL_INSN:
3900 	case JUMP_INSN:
3901 	  reset_origins (origins, age);
3902 	  break;
3903 
3904 	default:
3905 	  break;
3906 
3907 	case INSN:
3908 	  pat = PATTERN (insn);
3909 
3910 	  if (GET_CODE (pat) == PARALLEL)
3911 	    {
3912 	      rtx clobber = XVECEXP (pat, 0, 1);
3913 	      pat = XVECEXP (pat, 0, 0);
3914 	      if (GET_CODE (clobber) == CLOBBER
3915 		  && GET_CODE (XEXP (clobber, 0)) == REG)
3916 		{
3917 		  int cr = REGNO (XEXP (clobber, 0));
3918 		  int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3919 		  if (dump_file)
3920 		    fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3921 		  for (i = 0; i < mb; i++)
3922 		    {
3923 		      origins[cr + i] = cr + i;
3924 		      age[cr + i] = 0;
3925 		    }
3926 		}
3927 	      /* This happens with the DIV patterns.  */
3928 	      else if (GET_CODE (clobber) == SET)
3929 		{
3930 		  set_origin (clobber, insn, origins, age);
3931 		}
3932 	      else
3933 		break;
3934 	    }
3935 
3936 	  if (GET_CODE (pat) == SET)
3937 	    {
3938 	      set_origin (pat, insn, origins, age);
3939 	    }
3940 	  else if (GET_CODE (pat) == CLOBBER
3941 		   && GET_CODE (XEXP (pat, 0)) == REG)
3942 	    {
3943 	      if (REG_P (XEXP (pat, 0)))
3944 		{
3945 		  unsigned int reg = REGNO (XEXP (pat, 0));
3946 
3947 		  origins[reg] = reg;
3948 		  age[reg] = 0;
3949 		}
3950 	    }
3951 	}
3952     }
3953 }
3954 
3955 /* Remove any SETs where the destination is unneeded.  */
3956 static void
3957 rl78_remove_unused_sets (void)
3958 {
3959   rtx_insn *insn, *ninsn = NULL;
3960   rtx dest;
3961 
3962   for (insn = get_insns (); insn; insn = ninsn)
3963     {
3964       ninsn = next_nonnote_nondebug_insn (insn);
3965 
3966       rtx set = single_set (insn);
3967       if (set == NULL)
3968 	continue;
3969 
3970       dest = SET_DEST (set);
3971 
3972       if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3973 	continue;
3974 
3975       if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3976 	{
3977 	  if (dump_file)
3978 	    fprintf (dump_file, "deleting because the set register is never used.\n");
3979 	  delete_insn (insn);
3980 	}
3981     }
3982 }
3983 
3984 /* This is the top of the devritualization pass.  */
3985 static void
3986 rl78_reorg (void)
3987 {
3988   /* split2 only happens when optimizing, but we need all movSIs to be
3989      split now.  */
3990   if (optimize <= 0)
3991     split_all_insns ();
3992 
3993   rl78_alloc_physical_registers ();
3994 
3995   if (dump_file)
3996     {
3997       fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3998       print_rtl_with_bb (dump_file, get_insns (), 0);
3999     }
4000 
4001   rl78_propogate_register_origins ();
4002   rl78_calculate_death_notes ();
4003 
4004   if (dump_file)
4005     {
4006       fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4007       print_rtl_with_bb (dump_file, get_insns (), 0);
4008       fprintf (dump_file, "\n======================================================================\n");
4009     }
4010 
4011   rl78_remove_unused_sets ();
4012 
4013   /* The code after devirtualizing has changed so much that at this point
4014      we might as well just rescan everything.  Note that
4015      df_rescan_all_insns is not going to help here because it does not
4016      touch the artificial uses and defs.  */
4017   df_finish_pass (true);
4018   if (optimize > 1)
4019     df_live_add_problem ();
4020   df_scan_alloc (NULL);
4021   df_scan_blocks ();
4022 
4023   if (optimize)
4024     df_analyze ();
4025 }
4026 
4027 #undef  TARGET_RETURN_IN_MEMORY
4028 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4029 
4030 static bool
4031 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4032 {
4033   const HOST_WIDE_INT size = int_size_in_bytes (type);
4034   return (size == -1 || size > 8);
4035 }
4036 
4037 
4038 #undef  TARGET_RTX_COSTS
4039 #define TARGET_RTX_COSTS rl78_rtx_costs
4040 
4041 static bool rl78_rtx_costs (rtx   x,
4042 			    int   code,
4043 			    int   outer_code ATTRIBUTE_UNUSED,
4044 			    int   opno ATTRIBUTE_UNUSED,
4045 			    int * total,
4046 			    bool  speed ATTRIBUTE_UNUSED)
4047 {
4048   if (code == IF_THEN_ELSE)
4049     return COSTS_N_INSNS (10);
4050   if (GET_MODE (x) == SImode)
4051     {
4052       switch (code)
4053 	{
4054 	case MULT:
4055 	  if (RL78_MUL_RL78)
4056 	    *total = COSTS_N_INSNS (14);
4057 	  else if (RL78_MUL_G13)
4058 	    *total = COSTS_N_INSNS (29);
4059 	  else
4060 	    *total = COSTS_N_INSNS (500);
4061 	  return true;
4062 	case PLUS:
4063 	  *total = COSTS_N_INSNS (8);
4064 	  return true;
4065 	case ASHIFT:
4066 	case ASHIFTRT:
4067 	case LSHIFTRT:
4068 	  if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4069 	    {
4070 	      switch (INTVAL (XEXP (x, 1)))
4071 		{
4072 		case 0:  *total = COSTS_N_INSNS (0);	break;
4073 		case 1:  *total = COSTS_N_INSNS (6);	break;
4074 		case 2: case 3: case 4: case 5: case 6: case 7:
4075 		  *total = COSTS_N_INSNS (10); break;
4076 		case 8:  *total = COSTS_N_INSNS (6);	break;
4077 		case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4078 		  *total = COSTS_N_INSNS (10); break;
4079 		case 16: *total = COSTS_N_INSNS (3);	break;
4080 		case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4081 		  *total = COSTS_N_INSNS (4); break;
4082 		case 24: *total = COSTS_N_INSNS (4);	break;
4083 		case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4084 		  *total = COSTS_N_INSNS (5); break;
4085 		}
4086 	    }
4087 	  else
4088 	    *total = COSTS_N_INSNS (10+4*16);
4089 	  return true;
4090 	}
4091     }
4092   return false;
4093 }
4094 
4095 
4096 static GTY(()) section * saddr_section;
4097 static GTY(()) section * frodata_section;
4098 
4099 int
4100 rl78_saddr_p (rtx x)
4101 {
4102   const char * c;
4103 
4104   if (MEM_P (x))
4105     x = XEXP (x, 0);
4106   if (GET_CODE (x) == PLUS)
4107     x = XEXP (x, 0);
4108   if (GET_CODE (x) != SYMBOL_REF)
4109     return 0;
4110 
4111   c = XSTR (x, 0);
4112   if (memcmp (c, "@s.", 3) == 0)
4113     return 1;
4114 
4115   return 0;
4116 }
4117 
4118 int
4119 rl78_sfr_p (rtx x)
4120 {
4121   if (MEM_P (x))
4122     x = XEXP (x, 0);
4123   if (GET_CODE (x) != CONST_INT)
4124     return 0;
4125 
4126   if ((INTVAL (x) & 0xFF00) != 0xFF00)
4127     return 0;
4128 
4129   return 1;
4130 }
4131 
4132 #undef  TARGET_STRIP_NAME_ENCODING
4133 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4134 
4135 static const char *
4136 rl78_strip_name_encoding (const char * sym)
4137 {
4138   while (1)
4139     {
4140       if (*sym == '*')
4141 	sym++;
4142       else if (*sym == '@' && sym[2] == '.')
4143 	sym += 3;
4144       else
4145 	return sym;
4146     }
4147 }
4148 
4149 /* Like rl78_strip_name_encoding, but does not strip leading asterisks.  This
4150    is important if the stripped name is going to be passed to assemble_name()
4151    as that handles asterisk prefixed names in a special manner.  */
4152 
4153 static const char *
4154 rl78_strip_nonasm_name_encoding (const char * sym)
4155 {
4156   while (1)
4157     {
4158       if (*sym == '@' && sym[2] == '.')
4159 	sym += 3;
4160       else
4161 	return sym;
4162     }
4163 }
4164 
4165 
4166 static int
4167 rl78_attrlist_to_encoding (tree list, tree decl ATTRIBUTE_UNUSED)
4168 {
4169   while (list)
4170     {
4171       if (is_attribute_p ("saddr", TREE_PURPOSE (list)))
4172 	return 's';
4173       list = TREE_CHAIN (list);
4174     }
4175 
4176   return 0;
4177 }
4178 
4179 #define RL78_ATTRIBUTES(decl)				\
4180   (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl)		\
4181                 : DECL_ATTRIBUTES (decl)		\
4182                   ? (DECL_ATTRIBUTES (decl))		\
4183 		  : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4184 
4185 #undef  TARGET_ENCODE_SECTION_INFO
4186 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4187 
4188 static void
4189 rl78_encode_section_info (tree decl, rtx rtl, int first)
4190 {
4191   rtx rtlname;
4192   const char * oldname;
4193   char encoding;
4194   char * newname;
4195   tree idp;
4196   tree type;
4197   tree rl78_attributes;
4198 
4199   if (!first)
4200     return;
4201 
4202   rtlname = XEXP (rtl, 0);
4203 
4204   if (GET_CODE (rtlname) == SYMBOL_REF)
4205     oldname = XSTR (rtlname, 0);
4206   else if (GET_CODE (rtlname) == MEM
4207 	   && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4208     oldname = XSTR (XEXP (rtlname, 0), 0);
4209   else
4210     gcc_unreachable ();
4211 
4212   type = TREE_TYPE (decl);
4213   if (type == error_mark_node)
4214     return;
4215   if (! DECL_P (decl))
4216     return;
4217   rl78_attributes = RL78_ATTRIBUTES (decl);
4218 
4219   encoding = rl78_attrlist_to_encoding (rl78_attributes, decl);
4220 
4221   if (encoding)
4222     {
4223       newname = (char *) alloca (strlen (oldname) + 4);
4224       sprintf (newname, "@%c.%s", encoding, oldname);
4225       idp = get_identifier (newname);
4226       XEXP (rtl, 0) =
4227 	gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4228       SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4229       SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4230     }
4231 }
4232 
4233 #undef  TARGET_ASM_INIT_SECTIONS
4234 #define TARGET_ASM_INIT_SECTIONS 	rl78_asm_init_sections
4235 
4236 static void
4237 rl78_asm_init_sections (void)
4238 {
4239   saddr_section
4240     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4241 			   "\t.section .saddr,\"aw\",@progbits");
4242   frodata_section
4243     = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4244 			   "\t.section .frodata,\"aw\",@progbits");
4245 }
4246 
4247 #undef  TARGET_ASM_SELECT_SECTION
4248 #define TARGET_ASM_SELECT_SECTION	rl78_select_section
4249 
4250 static section *
4251 rl78_select_section (tree decl,
4252 		     int reloc ATTRIBUTE_UNUSED,
4253 		     unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4254 {
4255   int readonly = 1;
4256 
4257   switch (TREE_CODE (decl))
4258     {
4259     case VAR_DECL:
4260       if (!TREE_READONLY (decl)
4261 	  || TREE_SIDE_EFFECTS (decl)
4262 	  || !DECL_INITIAL (decl)
4263 	  || (DECL_INITIAL (decl) != error_mark_node
4264 	      && !TREE_CONSTANT (DECL_INITIAL (decl))))
4265 	readonly = 0;
4266       break;
4267     case CONSTRUCTOR:
4268       if (! TREE_CONSTANT (decl))
4269 	readonly = 0;
4270       break;
4271 
4272     default:
4273       break;
4274     }
4275 
4276   if (TREE_CODE (decl) == VAR_DECL)
4277     {
4278       const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4279 
4280       if (name[0] == '@' && name[2] == '.')
4281 	switch (name[1])
4282 	  {
4283 	  case 's':
4284 	    return saddr_section;
4285 	  }
4286 
4287       if (TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_FAR
4288 	  && readonly)
4289 	{
4290 	  return frodata_section;
4291 	}
4292     }
4293 
4294   if (readonly)
4295     return readonly_data_section;
4296 
4297   return data_section;
4298 }
4299 
4300 void
4301 rl78_output_labelref (FILE *file, const char *str)
4302 {
4303   const char *str2;
4304 
4305   str2 = targetm.strip_name_encoding (str);
4306   if (str2[0] != '.')
4307     fputs (user_label_prefix, file);
4308   fputs (str2, file);
4309 }
4310 
4311 void
4312 rl78_output_aligned_common (FILE *stream,
4313 			    tree decl ATTRIBUTE_UNUSED,
4314 			    const char *name,
4315 			    int size, int align, int global)
4316 {
4317   /* We intentionally don't use rl78_section_tag() here.  */
4318   if (name[0] == '@' && name[2] == '.')
4319     {
4320       const char *sec = 0;
4321       switch (name[1])
4322 	{
4323 	case 's':
4324 	  switch_to_section (saddr_section);
4325 	  sec = ".saddr";
4326 	  break;
4327 	}
4328       if (sec)
4329 	{
4330 	  const char *name2;
4331 	  int p2align = 0;
4332 
4333 	  while (align > BITS_PER_UNIT)
4334 	    {
4335 	      align /= 2;
4336 	      p2align ++;
4337 	    }
4338 	  name2 = targetm.strip_name_encoding (name);
4339 	  if (global)
4340 	    fprintf (stream, "\t.global\t_%s\n", name2);
4341 	  fprintf (stream, "\t.p2align %d\n", p2align);
4342 	  fprintf (stream, "\t.type\t_%s,@object\n", name2);
4343 	  fprintf (stream, "\t.size\t_%s,%d\n", name2, size);
4344 	  fprintf (stream, "_%s:\n\t.zero\t%d\n", name2, size);
4345 	  return;
4346 	}
4347     }
4348 
4349   if (!global)
4350     {
4351       fprintf (stream, "\t.local\t");
4352       assemble_name (stream, name);
4353       fprintf (stream, "\n");
4354     }
4355   fprintf (stream, "\t.comm\t");
4356   assemble_name (stream, name);
4357   fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4358 }
4359 
4360 #undef  TARGET_INSERT_ATTRIBUTES
4361 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4362 
4363 static void
4364 rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
4365 {
4366   if (TARGET_ES0
4367       && TREE_CODE (decl) == VAR_DECL
4368       && TREE_READONLY (decl)
4369       && TREE_ADDRESSABLE (decl)
4370       && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_GENERIC)
4371     {
4372       tree type = TREE_TYPE (decl);
4373       tree attr = TYPE_ATTRIBUTES (type);
4374       int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR);
4375 
4376       TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
4377     }
4378 }
4379 
4380 #undef  TARGET_ASM_INTEGER
4381 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4382 
4383 static bool
4384 rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
4385 {
4386   if (default_assemble_integer (x, size, aligned_p))
4387     return true;
4388 
4389   if (size == 4)
4390     {
4391       assemble_integer_with_op (".long\t", x);
4392       return true;
4393     }
4394 
4395   return false;
4396 }
4397 
4398 #undef  TARGET_UNWIND_WORD_MODE
4399 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4400 
4401 static machine_mode
4402 rl78_unwind_word_mode (void)
4403 {
4404   return HImode;
4405 }
4406 
4407 #ifndef USE_COLLECT2
4408 #undef  TARGET_ASM_CONSTRUCTOR
4409 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4410 #undef  TARGET_ASM_DESTRUCTOR
4411 #define TARGET_ASM_DESTRUCTOR  rl78_asm_destructor
4412 
4413 static void
4414 rl78_asm_ctor_dtor (rtx symbol, int priority, bool is_ctor)
4415 {
4416   section *sec;
4417 
4418   if (priority != DEFAULT_INIT_PRIORITY)
4419     {
4420       /* This section of the function is based upon code copied
4421 	 from: gcc/varasm.c:get_cdtor_priority_section().  */
4422       char buf[16];
4423 
4424       sprintf (buf, "%s.%.5u", is_ctor ? ".ctors" : ".dtors",
4425 	       MAX_INIT_PRIORITY - priority);
4426       sec = get_section (buf, 0, NULL);
4427     }
4428   else
4429     sec = is_ctor ? ctors_section : dtors_section;
4430 
4431   assemble_addr_to_section (symbol, sec);
4432 }
4433 
4434 static void
4435 rl78_asm_constructor (rtx symbol, int priority)
4436 {
4437   rl78_asm_ctor_dtor (symbol, priority, true);
4438 }
4439 
4440 static void
4441 rl78_asm_destructor (rtx symbol, int priority)
4442 {
4443   rl78_asm_ctor_dtor (symbol, priority, false);
4444 }
4445 #endif /* ! USE_COLLECT2 */
4446 
4447 /* Scan backwards through the insn chain looking to see if the flags
4448    have been set for a comparison of OP against OPERAND.  Start with
4449    the insn *before* the current insn.  */
4450 
4451 bool
4452 rl78_flags_already_set (rtx op, rtx operand)
4453 {
4454   /* We only track the Z flag.  */
4455   if (GET_CODE (op) != EQ && GET_CODE (op) != NE)
4456     return false;
4457 
4458   /* This should not happen, but let's be paranoid.  */
4459   if (current_output_insn == NULL_RTX)
4460     return false;
4461 
4462   rtx_insn *insn;
4463   bool res = false;
4464 
4465   for (insn = prev_nonnote_nondebug_insn (current_output_insn);
4466        insn != NULL_RTX;
4467        insn = prev_nonnote_nondebug_insn (insn))
4468     {
4469       if (LABEL_P (insn))
4470 	break;
4471 
4472       if (! INSN_P (insn))
4473 	continue;
4474 
4475       /* Make sure that the insn can be recognized.  */
4476       if (recog_memoized (insn) == -1)
4477 	continue;
4478 
4479       enum attr_update_Z updated = get_attr_update_Z (insn);
4480 
4481       rtx set = single_set (insn);
4482       bool must_break = (set != NULL_RTX && rtx_equal_p (operand, SET_DEST (set)));
4483 
4484       switch (updated)
4485 	{
4486 	case UPDATE_Z_NO:
4487 	  break;
4488 	case UPDATE_Z_CLOBBER:
4489 	  must_break = true;
4490 	  break;
4491 	case UPDATE_Z_UPDATE_Z:
4492 	  res = must_break;
4493 	  must_break = true;
4494 	  break;
4495 	default:
4496 	  gcc_unreachable ();
4497 	}
4498 
4499       if (must_break)
4500 	break;
4501     }
4502 
4503   /* We have to re-recognize the current insn as the call(s) to
4504      get_attr_update_Z() above will have overwritten the recog_data cache.  */
4505   recog_memoized (current_output_insn);
4506   cleanup_subreg_operands (current_output_insn);
4507   constrain_operands_cached (current_output_insn, 1);
4508 
4509   return res;
4510 }
4511 
4512 struct gcc_target targetm = TARGET_INITIALIZER;
4513 
4514 #include "gt-rl78.h"
4515