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