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