gcc/
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob8cf4974eecd5d3dab2fa5cbe6fa972f34789e5b7
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2015 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "alias.h"
26 #include "symtab.h"
27 #include "tree.h"
28 #include "fold-const.h"
29 #include "varasm.h"
30 #include "stor-layout.h"
31 #include "calls.h"
32 #include "rtl.h"
33 #include "regs.h"
34 #include "hard-reg-set.h"
35 #include "insn-config.h"
36 #include "conditions.h"
37 #include "output.h"
38 #include "insn-attr.h"
39 #include "flags.h"
40 #include "function.h"
41 #include "expmed.h"
42 #include "dojump.h"
43 #include "explow.h"
44 #include "emit-rtl.h"
45 #include "stmt.h"
46 #include "expr.h"
47 #include "insn-codes.h"
48 #include "optabs.h"
49 #include "libfuncs.h"
50 #include "recog.h"
51 #include "diagnostic-core.h"
52 #include "toplev.h"
53 #include "reload.h"
54 #include "dominance.h"
55 #include "cfg.h"
56 #include "cfgrtl.h"
57 #include "cfganal.h"
58 #include "lcm.h"
59 #include "cfgbuild.h"
60 #include "cfgcleanup.h"
61 #include "predict.h"
62 #include "basic-block.h"
63 #include "df.h"
64 #include "tm_p.h"
65 #include "debug.h"
66 #include "target.h"
67 #include "langhooks.h"
68 #include "rl78-protos.h"
69 #include "dumpfile.h"
70 #include "tree-pass.h"
71 #include "context.h"
72 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
73 #include "insn-flags.h" /* for gen_*(). */
74 #include "builtins.h"
75 #include "stringpool.h"
77 #include "target-def.h"
79 static inline bool is_interrupt_func (const_tree decl);
80 static inline bool is_brk_interrupt_func (const_tree decl);
81 static void rl78_reorg (void);
82 static const char *rl78_strip_name_encoding (const char *);
83 static const char *rl78_strip_nonasm_name_encoding (const char *);
84 static section * rl78_select_section (tree, int, unsigned HOST_WIDE_INT);
87 /* Debugging statements are tagged with DEBUG0 only so that they can
88 be easily enabled individually, by replacing the '0' with '1' as
89 needed. */
90 #define DEBUG0 0
91 #define DEBUG1 1
93 /* REGISTER_NAMES has the names for individual 8-bit registers, but
94 these have the names we need to use when referring to 16-bit
95 register pairs. */
96 static const char * const word_regnames[] =
98 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
99 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
100 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
101 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
102 "sp", "ap", "psw", "es", "cs"
105 struct GTY(()) machine_function
107 /* If set, the rest of the fields have been computed. */
108 int computed;
109 /* Which register pairs need to be pushed in the prologue. */
110 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
112 /* These fields describe the frame layout... */
113 /* arg pointer */
114 /* 4 bytes for saved PC */
115 int framesize_regs;
116 /* frame pointer */
117 int framesize_locals;
118 int framesize_outgoing;
119 /* stack pointer */
120 int framesize;
122 /* If set, recog is allowed to match against the "real" patterns. */
123 int real_insns_ok;
124 /* If set, recog is allowed to match against the "virtual" patterns. */
125 int virt_insns_ok;
126 /* Set if the current function needs to clean up any trampolines. */
127 int trampolines_used;
128 /* True if the ES register is used and hence
129 needs to be saved inside interrupt handlers. */
130 bool uses_es;
133 /* This is our init_machine_status, as set in
134 rl78_option_override. */
135 static struct machine_function *
136 rl78_init_machine_status (void)
138 struct machine_function *m;
140 m = ggc_cleared_alloc<machine_function> ();
141 m->virt_insns_ok = 1;
143 return m;
146 /* This pass converts virtual instructions using virtual registers, to
147 real instructions using real registers. Rather than run it as
148 reorg, we reschedule it before vartrack to help with debugging. */
149 namespace
151 const pass_data pass_data_rl78_devirt =
153 RTL_PASS, /* type */
154 "devirt", /* name */
155 OPTGROUP_NONE, /* optinfo_flags */
156 TV_MACH_DEP, /* tv_id */
157 0, /* properties_required */
158 0, /* properties_provided */
159 0, /* properties_destroyed */
160 0, /* todo_flags_start */
161 0, /* todo_flags_finish */
164 class pass_rl78_devirt : public rtl_opt_pass
166 public:
167 pass_rl78_devirt (gcc::context *ctxt)
168 : rtl_opt_pass (pass_data_rl78_devirt, ctxt)
172 /* opt_pass methods: */
173 virtual unsigned int execute (function *)
175 rl78_reorg ();
176 return 0;
179 } // anon namespace
181 rtl_opt_pass *
182 make_pass_rl78_devirt (gcc::context *ctxt)
184 return new pass_rl78_devirt (ctxt);
187 /* Redundant move elimination pass. Must be run after the basic block
188 reordering pass for the best effect. */
190 static unsigned int
191 move_elim_pass (void)
193 rtx_insn *insn, *ninsn;
194 rtx prev = NULL_RTX;
196 for (insn = get_insns (); insn; insn = ninsn)
198 rtx set;
200 ninsn = next_nonnote_nondebug_insn (insn);
202 if ((set = single_set (insn)) == NULL_RTX)
204 prev = NULL_RTX;
205 continue;
208 /* If we have two SET insns in a row (without anything
209 between them) and the source of the second one is the
210 destination of the first one, and vice versa, then we
211 can eliminate the second SET. */
212 if (prev
213 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
214 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
215 /* ... and none of the operands are volatile. */
216 && ! volatile_refs_p (SET_SRC (prev))
217 && ! volatile_refs_p (SET_DEST (prev))
218 && ! volatile_refs_p (SET_SRC (set))
219 && ! volatile_refs_p (SET_DEST (set)))
221 if (dump_file)
222 fprintf (dump_file, " Delete insn %d because it is redundant\n",
223 INSN_UID (insn));
225 delete_insn (insn);
226 prev = NULL_RTX;
228 else
229 prev = set;
232 if (dump_file)
233 print_rtl_with_bb (dump_file, get_insns (), 0);
235 return 0;
238 namespace
240 const pass_data pass_data_rl78_move_elim =
242 RTL_PASS, /* type */
243 "move_elim", /* name */
244 OPTGROUP_NONE, /* optinfo_flags */
245 TV_MACH_DEP, /* tv_id */
246 0, /* properties_required */
247 0, /* properties_provided */
248 0, /* properties_destroyed */
249 0, /* todo_flags_start */
250 0, /* todo_flags_finish */
253 class pass_rl78_move_elim : public rtl_opt_pass
255 public:
256 pass_rl78_move_elim (gcc::context *ctxt)
257 : rtl_opt_pass (pass_data_rl78_move_elim, ctxt)
261 /* opt_pass methods: */
262 virtual unsigned int execute (function *) { return move_elim_pass (); }
264 } // anon namespace
266 rtl_opt_pass *
267 make_pass_rl78_move_elim (gcc::context *ctxt)
269 return new pass_rl78_move_elim (ctxt);
272 #undef TARGET_ASM_FILE_START
273 #define TARGET_ASM_FILE_START rl78_asm_file_start
275 static void
276 rl78_asm_file_start (void)
278 int i;
280 if (TARGET_G10)
282 /* The memory used is 0xffec8 to 0xffedf; real registers are in
283 0xffee0 to 0xffee7. */
284 for (i = 8; i < 32; i++)
285 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
287 else
289 for (i = 0; i < 8; i++)
291 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
292 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
293 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
297 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
298 struct register_pass_info rl78_devirt_info =
300 rl78_devirt_pass,
301 "pro_and_epilogue",
303 PASS_POS_INSERT_BEFORE
306 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
307 struct register_pass_info rl78_move_elim_info =
309 rl78_move_elim_pass,
310 "bbro",
312 PASS_POS_INSERT_AFTER
315 register_pass (& rl78_devirt_info);
316 register_pass (& rl78_move_elim_info);
319 void
320 rl78_output_symbol_ref (FILE * file, rtx sym)
322 tree type = SYMBOL_REF_DECL (sym);
323 const char *str = XSTR (sym, 0);
325 if (str[0] == '*')
327 fputs (str + 1, file);
329 else
331 str = rl78_strip_nonasm_name_encoding (str);
332 if (type && TREE_CODE (type) == FUNCTION_DECL)
334 fprintf (file, "%%code(");
335 assemble_name (file, str);
336 fprintf (file, ")");
338 else
339 assemble_name (file, str);
343 #undef TARGET_OPTION_OVERRIDE
344 #define TARGET_OPTION_OVERRIDE rl78_option_override
346 static void
347 rl78_option_override (void)
349 flag_omit_frame_pointer = 1;
350 flag_no_function_cse = 1;
351 flag_split_wide_types = 0;
353 init_machine_status = rl78_init_machine_status;
355 if (TARGET_ALLREGS)
357 int i;
359 for (i = 24; i < 32; i++)
360 fixed_regs[i] = 0;
363 if (TARGET_ES0
364 && strcmp (lang_hooks.name, "GNU C")
365 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
366 && strcmp (lang_hooks.name, "GNU GIMPLE"))
367 /* Address spaces are currently only supported by C. */
368 error ("-mes0 can only be used with C");
370 switch (rl78_cpu_type)
372 case CPU_UNINIT:
373 rl78_cpu_type = CPU_G14;
374 if (rl78_mul_type == MUL_UNINIT)
375 rl78_mul_type = MUL_NONE;
376 break;
378 case CPU_G10:
379 switch (rl78_mul_type)
381 case MUL_UNINIT: rl78_mul_type = MUL_NONE; break;
382 case MUL_NONE: break;
383 case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
384 case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
386 break;
388 case CPU_G13:
389 switch (rl78_mul_type)
391 case MUL_UNINIT: rl78_mul_type = MUL_G13; break;
392 case MUL_NONE: break;
393 case MUL_G13: break;
394 /* The S2 core does not have mul/div instructions. */
395 case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
397 break;
399 case CPU_G14:
400 switch (rl78_mul_type)
402 case MUL_UNINIT: rl78_mul_type = MUL_G14; break;
403 case MUL_NONE: break;
404 case MUL_G14: break;
405 /* The G14 core does not have the hardware multiply peripheral used by the
406 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
407 case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
409 break;
413 /* Most registers are 8 bits. Some are 16 bits because, for example,
414 gcc doesn't like dealing with $FP as a register pair (the second
415 half of $fp is also 2 to keep reload happy wrt register pairs, but
416 no register class includes it). This table maps register numbers
417 to size in bytes. */
418 static const int register_sizes[] =
420 1, 1, 1, 1, 1, 1, 1, 1,
421 1, 1, 1, 1, 1, 1, 1, 1,
422 1, 1, 1, 1, 1, 1, 2, 2,
423 1, 1, 1, 1, 1, 1, 1, 1,
424 2, 2, 1, 1, 1
427 /* Predicates used in the MD patterns. This one is true when virtual
428 insns may be matched, which typically means before (or during) the
429 devirt pass. */
430 bool
431 rl78_virt_insns_ok (void)
433 if (cfun)
434 return cfun->machine->virt_insns_ok;
435 return true;
438 /* Predicates used in the MD patterns. This one is true when real
439 insns may be matched, which typically means after (or during) the
440 devirt pass. */
441 bool
442 rl78_real_insns_ok (void)
444 if (cfun)
445 return cfun->machine->real_insns_ok;
446 return false;
449 /* Implements HARD_REGNO_NREGS. */
451 rl78_hard_regno_nregs (int regno, machine_mode mode)
453 int rs = register_sizes[regno];
454 if (rs < 1)
455 rs = 1;
456 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
459 /* Implements HARD_REGNO_MODE_OK. */
461 rl78_hard_regno_mode_ok (int regno, machine_mode mode)
463 int s = GET_MODE_SIZE (mode);
465 if (s < 1)
466 return 0;
467 /* These are not to be used by gcc. */
468 if (regno == 23 || regno == ES_REG || regno == CS_REG)
469 return 0;
470 /* $fp can always be accessed as a 16-bit value. */
471 if (regno == FP_REG && s == 2)
472 return 1;
473 if (regno < SP_REG)
475 /* Since a reg-reg move is really a reg-mem move, we must
476 enforce alignment. */
477 if (s > 1 && (regno % 2))
478 return 0;
479 return 1;
481 if (s == CC_REGNUM)
482 return (mode == BImode);
483 /* All other registers must be accessed in their natural sizes. */
484 if (s == register_sizes [regno])
485 return 1;
486 return 0;
489 /* Simplify_gen_subreg() doesn't handle memory references the way we
490 need it to below, so we use this function for when we must get a
491 valid subreg in a "natural" state. */
492 static rtx
493 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
495 if (GET_CODE (r) == MEM)
496 return adjust_address (r, mode, byte);
497 else
498 return simplify_gen_subreg (mode, r, omode, byte);
501 /* Used by movsi. Split SImode moves into two HImode moves, using
502 appropriate patterns for the upper and lower halves of symbols. */
503 void
504 rl78_expand_movsi (rtx *operands)
506 rtx op00, op02, op10, op12;
508 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
509 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
510 if (GET_CODE (operands[1]) == CONST
511 || GET_CODE (operands[1]) == SYMBOL_REF)
513 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
514 op10 = gen_rtx_CONST (HImode, op10);
515 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
516 op12 = gen_rtx_CONST (HImode, op12);
518 else
520 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
521 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
524 if (rtx_equal_p (operands[0], operands[1]))
526 else if (rtx_equal_p (op00, op12))
528 emit_move_insn (op02, op12);
529 emit_move_insn (op00, op10);
531 else
533 emit_move_insn (op00, op10);
534 emit_move_insn (op02, op12);
538 /* Generate code to move an SImode value. */
539 void
540 rl78_split_movsi (rtx *operands, enum machine_mode omode)
542 rtx op00, op02, op10, op12;
544 op00 = rl78_subreg (HImode, operands[0], omode, 0);
545 op02 = rl78_subreg (HImode, operands[0], omode, 2);
547 if (GET_CODE (operands[1]) == CONST
548 || GET_CODE (operands[1]) == SYMBOL_REF)
550 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
551 op10 = gen_rtx_CONST (HImode, op10);
552 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
553 op12 = gen_rtx_CONST (HImode, op12);
555 else
557 op10 = rl78_subreg (HImode, operands[1], omode, 0);
558 op12 = rl78_subreg (HImode, operands[1], omode, 2);
561 if (rtx_equal_p (operands[0], operands[1]))
563 else if (rtx_equal_p (op00, op12))
565 operands[2] = op02;
566 operands[4] = op12;
567 operands[3] = op00;
568 operands[5] = op10;
570 else
572 operands[2] = op00;
573 operands[4] = op10;
574 operands[3] = op02;
575 operands[5] = op12;
579 /* Used by various two-operand expanders which cannot accept all
580 operands in the "far" namespace. Force some such operands into
581 registers so that each pattern has at most one far operand. */
583 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
585 int did = 0;
586 rtx temp_reg = NULL;
588 /* FIXME: in the future, be smarter about only doing this if the
589 other operand is also far, assuming the devirtualizer can also
590 handle that. */
591 if (rl78_far_p (operands[0]))
593 temp_reg = operands[0];
594 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
595 did = 1;
597 if (!did)
598 return 0;
600 emit_insn (gen (operands[0], operands[1]));
601 if (temp_reg)
602 emit_move_insn (temp_reg, operands[0]);
603 return 1;
606 /* Likewise, but for three-operand expanders. */
608 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
610 int did = 0;
611 rtx temp_reg = NULL;
613 /* As an exception, we allow two far operands if they're identical
614 and the third operand is not a MEM. This allows global variables
615 to be incremented, for example. */
616 if (rtx_equal_p (operands[0], operands[1])
617 && ! MEM_P (operands[2]))
618 return 0;
620 /* FIXME: Likewise. */
621 if (rl78_far_p (operands[1]))
623 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
624 emit_move_insn (temp_reg, operands[1]);
625 operands[1] = temp_reg;
626 did = 1;
628 if (rl78_far_p (operands[0]))
630 temp_reg = operands[0];
631 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
632 did = 1;
634 if (!did)
635 return 0;
637 emit_insn (gen (operands[0], operands[1], operands[2]));
638 if (temp_reg)
639 emit_move_insn (temp_reg, operands[0]);
640 return 1;
643 #undef TARGET_CAN_ELIMINATE
644 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
646 static bool
647 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
649 return true;
652 /* Returns true if the given register needs to be saved by the
653 current function. */
654 static bool
655 need_to_save (unsigned int regno)
657 if (is_interrupt_func (cfun->decl))
659 /* We don't know what devirt will need */
660 if (regno < 8)
661 return true;
663 /* We don't need to save registers that have
664 been reserved for interrupt handlers. */
665 if (regno > 23)
666 return false;
668 /* If the handler is a non-leaf function then it may call
669 non-interrupt aware routines which will happily clobber
670 any call_used registers, so we have to preserve them.
671 We do not have to worry about the frame pointer register
672 though, as that is handled below. */
673 if (!crtl->is_leaf && call_used_regs[regno] && regno < 22)
674 return true;
676 /* Otherwise we only have to save a register, call_used
677 or not, if it is used by this handler. */
678 return df_regs_ever_live_p (regno);
681 if (regno == FRAME_POINTER_REGNUM
682 && (frame_pointer_needed || df_regs_ever_live_p (regno)))
683 return true;
684 if (fixed_regs[regno])
685 return false;
686 if (crtl->calls_eh_return)
687 return true;
688 if (df_regs_ever_live_p (regno)
689 && !call_used_regs[regno])
690 return true;
691 return false;
694 /* We use this to wrap all emitted insns in the prologue. */
695 static rtx
696 F (rtx x)
698 RTX_FRAME_RELATED_P (x) = 1;
699 return x;
702 /* Compute all the frame-related fields in our machine_function
703 structure. */
704 static void
705 rl78_compute_frame_info (void)
707 int i;
709 cfun->machine->computed = 1;
710 cfun->machine->framesize_regs = 0;
711 cfun->machine->framesize_locals = get_frame_size ();
712 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
714 for (i = 0; i < 16; i ++)
715 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
717 cfun->machine->need_to_push [i] = 1;
718 cfun->machine->framesize_regs += 2;
720 else
721 cfun->machine->need_to_push [i] = 0;
723 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
724 cfun->machine->framesize_locals ++;
726 cfun->machine->framesize = (cfun->machine->framesize_regs
727 + cfun->machine->framesize_locals
728 + cfun->machine->framesize_outgoing);
731 /* Returns true if the provided function has the specified attribute. */
732 static inline bool
733 has_func_attr (const_tree decl, const char * func_attr)
735 if (decl == NULL_TREE)
736 decl = current_function_decl;
738 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
741 /* Returns true if the provided function has the "interrupt" attribute. */
742 static inline bool
743 is_interrupt_func (const_tree decl)
745 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
748 /* Returns true if the provided function has the "brk_interrupt" attribute. */
749 static inline bool
750 is_brk_interrupt_func (const_tree decl)
752 return has_func_attr (decl, "brk_interrupt");
755 /* Check "interrupt" attributes. */
756 static tree
757 rl78_handle_func_attribute (tree * node,
758 tree name,
759 tree args,
760 int flags ATTRIBUTE_UNUSED,
761 bool * no_add_attrs)
763 gcc_assert (DECL_P (* node));
764 gcc_assert (args == NULL_TREE);
766 if (TREE_CODE (* node) != FUNCTION_DECL)
768 warning (OPT_Wattributes, "%qE attribute only applies to functions",
769 name);
770 * no_add_attrs = true;
773 /* FIXME: We ought to check that the interrupt and exception
774 handler attributes have been applied to void functions. */
775 return NULL_TREE;
778 /* Check "naked" attributes. */
779 static tree
780 rl78_handle_naked_attribute (tree * node,
781 tree name ATTRIBUTE_UNUSED,
782 tree args,
783 int flags ATTRIBUTE_UNUSED,
784 bool * no_add_attrs)
786 gcc_assert (DECL_P (* node));
787 gcc_assert (args == NULL_TREE);
789 if (TREE_CODE (* node) != FUNCTION_DECL)
791 warning (OPT_Wattributes, "naked attribute only applies to functions");
792 * no_add_attrs = true;
795 /* Disable warnings about this function - eg reaching the end without
796 seeing a return statement - because the programmer is doing things
797 that gcc does not know about. */
798 TREE_NO_WARNING (* node) = 1;
800 return NULL_TREE;
803 /* Check "saddr" attributes. */
804 static tree
805 rl78_handle_saddr_attribute (tree * node,
806 tree name,
807 tree args ATTRIBUTE_UNUSED,
808 int flags ATTRIBUTE_UNUSED,
809 bool * no_add_attrs)
811 gcc_assert (DECL_P (* node));
813 if (TREE_CODE (* node) == FUNCTION_DECL)
815 warning (OPT_Wattributes, "%qE attribute doesn't apply to functions",
816 name);
817 * no_add_attrs = true;
820 return NULL_TREE;
823 #undef TARGET_ATTRIBUTE_TABLE
824 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
826 /* Table of RL78-specific attributes. */
827 const struct attribute_spec rl78_attribute_table[] =
829 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
830 affects_type_identity. */
831 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
832 false },
833 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
834 false },
835 { "naked", 0, 0, true, false, false, rl78_handle_naked_attribute,
836 false },
837 { "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute,
838 false },
839 { NULL, 0, 0, false, false, false, NULL, false }
844 /* Break down an address RTX into its component base/index/addend
845 portions and return TRUE if the address is of a valid form, else
846 FALSE. */
847 static bool
848 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
850 *base = NULL_RTX;
851 *index = NULL_RTX;
852 *addend = NULL_RTX;
854 if (GET_CODE (x) == UNSPEC
855 && XINT (x, 1) == UNS_ES_ADDR)
856 x = XVECEXP (x, 0, 1);
858 if (GET_CODE (x) == REG)
860 *base = x;
861 return true;
864 /* We sometimes get these without the CONST wrapper */
865 if (GET_CODE (x) == PLUS
866 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
867 && GET_CODE (XEXP (x, 1)) == CONST_INT)
869 *addend = x;
870 return true;
873 if (GET_CODE (x) == PLUS)
875 *base = XEXP (x, 0);
876 x = XEXP (x, 1);
878 if (GET_CODE (*base) == SUBREG)
880 if (GET_MODE (*base) == HImode
881 && GET_MODE (XEXP (*base, 0)) == SImode
882 && GET_CODE (XEXP (*base, 0)) == REG)
884 /* This is a throw-away rtx just to tell everyone
885 else what effective register we're using. */
886 *base = gen_rtx_REG (HImode, REGNO (XEXP (*base, 0)));
890 if (GET_CODE (*base) != REG
891 && GET_CODE (x) == REG)
893 rtx tmp = *base;
894 *base = x;
895 x = tmp;
898 if (GET_CODE (*base) != REG)
899 return false;
901 if (GET_CODE (x) == ZERO_EXTEND
902 && GET_CODE (XEXP (x, 0)) == REG)
904 *index = XEXP (x, 0);
905 return false;
909 switch (GET_CODE (x))
911 case PLUS:
912 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
913 && GET_CODE (XEXP (x, 0)) == CONST_INT)
915 *addend = x;
916 return true;
918 /* fall through */
919 case MEM:
920 case REG:
921 return false;
923 case SUBREG:
924 switch (GET_CODE (XEXP (x, 0)))
926 case CONST:
927 case SYMBOL_REF:
928 case CONST_INT:
929 *addend = x;
930 return true;
931 default:
932 return false;
935 case CONST:
936 case SYMBOL_REF:
937 case CONST_INT:
938 *addend = x;
939 return true;
941 default:
942 return false;
945 return false;
948 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
949 addressing. */
950 bool
951 rl78_hl_b_c_addr_p (rtx op)
953 rtx hl, bc;
955 if (GET_CODE (op) != PLUS)
956 return false;
957 hl = XEXP (op, 0);
958 bc = XEXP (op, 1);
959 if (GET_CODE (hl) == ZERO_EXTEND)
961 rtx tmp = hl;
962 hl = bc;
963 bc = tmp;
965 if (GET_CODE (hl) != REG)
966 return false;
967 if (GET_CODE (bc) != ZERO_EXTEND)
968 return false;
969 bc = XEXP (bc, 0);
970 if (GET_CODE (bc) != REG)
971 return false;
972 if (REGNO (hl) != HL_REG)
973 return false;
974 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
975 return false;
977 return true;
980 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
982 /* Return the appropriate mode for a named address address. */
984 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
985 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
987 static enum machine_mode
988 rl78_addr_space_address_mode (addr_space_t addrspace)
990 switch (addrspace)
992 case ADDR_SPACE_GENERIC:
993 return HImode;
994 case ADDR_SPACE_NEAR:
995 return HImode;
996 case ADDR_SPACE_FAR:
997 return SImode;
998 default:
999 gcc_unreachable ();
1003 /* Used in various constraints and predicates to match operands in the
1004 "far" address space. */
1006 rl78_far_p (rtx x)
1008 if (! MEM_P (x))
1009 return 0;
1010 #if DEBUG0
1011 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
1012 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
1013 #endif
1015 /* Not all far addresses are legitimate, because the devirtualizer
1016 can't handle them. */
1017 if (! rl78_as_legitimate_address (GET_MODE (x), XEXP (x, 0), false, ADDR_SPACE_FAR))
1018 return 0;
1020 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x))) == 32;
1023 /* Return the appropriate mode for a named address pointer. */
1024 #undef TARGET_ADDR_SPACE_POINTER_MODE
1025 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1027 static machine_mode
1028 rl78_addr_space_pointer_mode (addr_space_t addrspace)
1030 switch (addrspace)
1032 case ADDR_SPACE_GENERIC:
1033 return HImode;
1034 case ADDR_SPACE_NEAR:
1035 return HImode;
1036 case ADDR_SPACE_FAR:
1037 return SImode;
1038 default:
1039 gcc_unreachable ();
1043 /* Returns TRUE for valid addresses. */
1044 #undef TARGET_VALID_POINTER_MODE
1045 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1047 static bool
1048 rl78_valid_pointer_mode (machine_mode m)
1050 return (m == HImode || m == SImode);
1053 #undef TARGET_LEGITIMATE_CONSTANT_P
1054 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1056 static bool
1057 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
1059 return true;
1062 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1063 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1065 bool
1066 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
1067 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
1069 rtx base, index, addend;
1070 bool is_far_addr = false;
1071 int as_bits;
1073 as_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (as));
1075 if (GET_CODE (x) == UNSPEC
1076 && XINT (x, 1) == UNS_ES_ADDR)
1078 x = XVECEXP (x, 0, 1);
1079 is_far_addr = true;
1082 if (as_bits == 16 && is_far_addr)
1083 return false;
1085 if (! characterize_address (x, &base, &index, &addend))
1086 return false;
1088 /* We can't extract the high/low portions of a PLUS address
1089 involving a register during devirtualization, so make sure all
1090 such __far addresses do not have addends. This forces GCC to do
1091 the sum separately. */
1092 if (addend && base && as_bits == 32 && GET_MODE (base) == SImode)
1093 return false;
1095 if (base && index)
1097 int ir = REGNO (index);
1098 int br = REGNO (base);
1100 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1101 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
1102 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
1103 return false;
1106 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
1107 return false;
1109 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
1110 && REGNO (base) >= 8 && REGNO (base) <= 31)
1111 return false;
1113 return true;
1116 /* Determine if one named address space is a subset of another. */
1117 #undef TARGET_ADDR_SPACE_SUBSET_P
1118 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1120 static bool
1121 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1123 int subset_bits;
1124 int superset_bits;
1126 subset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset));
1127 superset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset));
1129 return (subset_bits <= superset_bits);
1132 #undef TARGET_ADDR_SPACE_CONVERT
1133 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1135 /* Convert from one address space to another. */
1136 static rtx
1137 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
1139 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1140 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1141 rtx result;
1142 int to_bits;
1143 int from_bits;
1145 to_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as));
1146 from_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as));
1148 if (to_bits < from_bits)
1150 rtx tmp;
1151 /* This is unpredictable, as we're truncating off usable address
1152 bits. */
1154 warning (OPT_Waddress, "converting far pointer to near pointer");
1155 result = gen_reg_rtx (HImode);
1156 if (GET_CODE (op) == SYMBOL_REF
1157 || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER))
1158 tmp = gen_rtx_raw_SUBREG (HImode, op, 0);
1159 else
1160 tmp = simplify_subreg (HImode, op, SImode, 0);
1161 gcc_assert (tmp != NULL_RTX);
1162 emit_move_insn (result, tmp);
1163 return result;
1165 else if (to_bits > from_bits)
1167 /* This always works. */
1168 result = gen_reg_rtx (SImode);
1169 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
1170 if (TREE_CODE (from_type) == POINTER_TYPE
1171 && TREE_CODE (TREE_TYPE (from_type)) == FUNCTION_TYPE)
1172 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
1173 else
1174 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), GEN_INT (0x0f));
1175 return result;
1177 else
1178 return op;
1179 gcc_unreachable ();
1182 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1183 bool
1184 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
1185 addr_space_t address_space ATTRIBUTE_UNUSED,
1186 int outer_code ATTRIBUTE_UNUSED, int index_code)
1188 if (regno <= SP_REG && regno >= 16)
1189 return true;
1190 if (index_code == REG)
1191 return (regno == HL_REG);
1192 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
1193 return true;
1194 return false;
1197 /* Implements MODE_CODE_BASE_REG_CLASS. */
1198 enum reg_class
1199 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1200 addr_space_t address_space ATTRIBUTE_UNUSED,
1201 int outer_code ATTRIBUTE_UNUSED,
1202 int index_code ATTRIBUTE_UNUSED)
1204 return V_REGS;
1207 /* Typical stack layout should looks like this after the function's prologue:
1210 -- ^
1211 | | \ |
1212 | | arguments saved | Increasing
1213 | | on the stack | addresses
1214 PARENT arg pointer -> | | /
1215 -------------------------- ---- -------------------
1216 CHILD |ret | return address
1218 | | \
1219 | | call saved
1220 | | registers
1221 frame pointer -> | | /
1223 | | \
1224 | | local
1225 | | variables
1226 | | /
1228 | | \
1229 | | outgoing | Decreasing
1230 | | arguments | addresses
1231 current stack pointer -> | | / |
1232 -------------------------- ---- ------------------ V
1233 | | */
1235 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1236 described in the machine_Function struct definition, above. */
1238 rl78_initial_elimination_offset (int from, int to)
1240 int rv = 0; /* as if arg to arg */
1242 rl78_compute_frame_info ();
1244 switch (to)
1246 case STACK_POINTER_REGNUM:
1247 rv += cfun->machine->framesize_outgoing;
1248 rv += cfun->machine->framesize_locals;
1249 /* Fall through. */
1250 case FRAME_POINTER_REGNUM:
1251 rv += cfun->machine->framesize_regs;
1252 rv += 4;
1253 break;
1254 default:
1255 gcc_unreachable ();
1258 switch (from)
1260 case FRAME_POINTER_REGNUM:
1261 rv -= 4;
1262 rv -= cfun->machine->framesize_regs;
1263 case ARG_POINTER_REGNUM:
1264 break;
1265 default:
1266 gcc_unreachable ();
1269 return rv;
1272 static int
1273 rl78_is_naked_func (void)
1275 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1278 /* Expand the function prologue (from the prologue pattern). */
1279 void
1280 rl78_expand_prologue (void)
1282 int i, fs;
1283 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1284 rtx ax = gen_rtx_REG (HImode, AX_REG);
1285 int rb = 0;
1287 if (rl78_is_naked_func ())
1288 return;
1290 /* Always re-compute the frame info - the register usage may have changed. */
1291 rl78_compute_frame_info ();
1293 if (flag_stack_usage_info)
1294 current_function_static_stack_size = cfun->machine->framesize;
1296 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1297 for (i = 0; i < 4; i++)
1298 if (cfun->machine->need_to_push [i])
1300 /* Select Bank 0 if we are using any registers from Bank 0. */
1301 emit_insn (gen_sel_rb (GEN_INT (0)));
1302 break;
1305 for (i = 0; i < 16; i++)
1306 if (cfun->machine->need_to_push [i])
1308 int reg = i * 2;
1310 if (TARGET_G10)
1312 if (reg >= 8)
1314 emit_move_insn (ax, gen_rtx_REG (HImode, reg));
1315 reg = AX_REG;
1318 else
1320 int need_bank = i/4;
1322 if (need_bank != rb)
1324 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1325 rb = need_bank;
1329 F (emit_insn (gen_push (gen_rtx_REG (HImode, reg))));
1332 if (rb != 0)
1333 emit_insn (gen_sel_rb (GEN_INT (0)));
1335 /* Save ES register inside interrupt functions if it is used. */
1336 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1338 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG)));
1339 F (emit_insn (gen_push (ax)));
1342 if (frame_pointer_needed)
1344 F (emit_move_insn (ax, sp));
1345 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM), ax));
1348 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1349 if (fs > 0)
1351 /* If we need to subtract more than 254*3 then it is faster and
1352 smaller to move SP into AX and perform the subtraction there. */
1353 if (fs > 254 * 3)
1355 rtx insn;
1357 emit_move_insn (ax, sp);
1358 emit_insn (gen_subhi3 (ax, ax, GEN_INT (fs)));
1359 insn = F (emit_move_insn (sp, ax));
1360 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
1361 gen_rtx_SET (sp, gen_rtx_PLUS (HImode, sp,
1362 GEN_INT (-fs))));
1364 else
1366 while (fs > 0)
1368 int fs_byte = (fs > 254) ? 254 : fs;
1370 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1371 fs -= fs_byte;
1377 /* Expand the function epilogue (from the epilogue pattern). */
1378 void
1379 rl78_expand_epilogue (void)
1381 int i, fs;
1382 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1383 rtx ax = gen_rtx_REG (HImode, AX_REG);
1384 int rb = 0;
1386 if (rl78_is_naked_func ())
1387 return;
1389 if (frame_pointer_needed)
1391 emit_move_insn (ax, gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1392 emit_move_insn (sp, ax);
1394 else
1396 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1397 if (fs > 254 * 3)
1399 emit_move_insn (ax, sp);
1400 emit_insn (gen_addhi3 (ax, ax, GEN_INT (fs)));
1401 emit_move_insn (sp, ax);
1403 else
1405 while (fs > 0)
1407 int fs_byte = (fs > 254) ? 254 : fs;
1409 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1410 fs -= fs_byte;
1415 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1417 emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1418 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode, A_REG)));
1421 for (i = 15; i >= 0; i--)
1422 if (cfun->machine->need_to_push [i])
1424 rtx dest = gen_rtx_REG (HImode, i * 2);
1426 if (TARGET_G10)
1428 if (i < 8)
1429 emit_insn (gen_pop (dest));
1430 else
1432 emit_insn (gen_pop (ax));
1433 emit_move_insn (dest, ax);
1434 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1435 emit_insn (gen_use (dest));
1438 else
1440 int need_bank = i / 4;
1442 if (need_bank != rb)
1444 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1445 rb = need_bank;
1447 emit_insn (gen_pop (dest));
1451 if (rb != 0)
1452 emit_insn (gen_sel_rb (GEN_INT (0)));
1454 if (cfun->machine->trampolines_used)
1455 emit_insn (gen_trampoline_uninit ());
1457 if (is_brk_interrupt_func (cfun->decl))
1458 emit_jump_insn (gen_brk_interrupt_return ());
1459 else if (is_interrupt_func (cfun->decl))
1460 emit_jump_insn (gen_interrupt_return ());
1461 else
1462 emit_jump_insn (gen_rl78_return ());
1465 /* Likewise, for exception handlers. */
1466 void
1467 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1469 /* FIXME - replace this with an indirect jump with stack adjust. */
1470 emit_jump_insn (gen_rl78_return ());
1473 #undef TARGET_ASM_FUNCTION_PROLOGUE
1474 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1476 /* We don't use this to actually emit the function prologue. We use
1477 this to insert a comment in the asm file describing the
1478 function. */
1479 static void
1480 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1482 int i;
1484 if (cfun->machine->framesize == 0)
1485 return;
1486 fprintf (file, "\t; start of function\n");
1488 if (cfun->machine->framesize_regs)
1490 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1491 for (i = 0; i < 16; i ++)
1492 if (cfun->machine->need_to_push[i])
1493 fprintf (file, " %s", word_regnames[i*2]);
1494 fprintf (file, "\n");
1497 if (frame_pointer_needed)
1498 fprintf (file, "\t; $fp points here (r22)\n");
1500 if (cfun->machine->framesize_locals)
1501 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1502 cfun->machine->framesize_locals == 1 ? "" : "s");
1504 if (cfun->machine->framesize_outgoing)
1505 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1506 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1508 if (cfun->machine->uses_es)
1509 fprintf (file, "\t; uses ES register\n");
1512 /* Return an RTL describing where a function return value of type RET_TYPE
1513 is held. */
1515 #undef TARGET_FUNCTION_VALUE
1516 #define TARGET_FUNCTION_VALUE rl78_function_value
1518 static rtx
1519 rl78_function_value (const_tree ret_type,
1520 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1521 bool outgoing ATTRIBUTE_UNUSED)
1523 machine_mode mode = TYPE_MODE (ret_type);
1525 return gen_rtx_REG (mode, 8);
1528 #undef TARGET_PROMOTE_FUNCTION_MODE
1529 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1531 static machine_mode
1532 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1533 machine_mode mode,
1534 int *punsignedp ATTRIBUTE_UNUSED,
1535 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1537 return mode;
1540 /* Return an RTL expression describing the register holding a function
1541 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1542 be passed on the stack. CUM describes the previous parameters to the
1543 function and NAMED is false if the parameter is part of a variable
1544 parameter list, or the last named parameter before the start of a
1545 variable parameter list. */
1547 #undef TARGET_FUNCTION_ARG
1548 #define TARGET_FUNCTION_ARG rl78_function_arg
1550 static rtx
1551 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1552 machine_mode mode ATTRIBUTE_UNUSED,
1553 const_tree type ATTRIBUTE_UNUSED,
1554 bool named ATTRIBUTE_UNUSED)
1556 return NULL_RTX;
1559 #undef TARGET_FUNCTION_ARG_ADVANCE
1560 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1562 static void
1563 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1564 bool named ATTRIBUTE_UNUSED)
1566 int rounded_size;
1567 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1569 rounded_size = ((mode == BLKmode)
1570 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1571 if (rounded_size & 1)
1572 rounded_size ++;
1573 (*cum) += rounded_size;
1576 #undef TARGET_FUNCTION_ARG_BOUNDARY
1577 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1579 static unsigned int
1580 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1581 const_tree type ATTRIBUTE_UNUSED)
1583 return 16;
1586 /* Supported modifier letters:
1588 A - address of a MEM
1589 S - SADDR form of a real register
1590 v - real register corresponding to a virtual register
1591 m - minus - negative of CONST_INT value.
1592 C - inverse of a conditional (NE vs EQ for example)
1593 C - complement of an integer
1594 z - collapsed conditional
1595 s - shift count mod 8
1596 S - shift count mod 16
1597 r - reverse shift count (8-(count mod 8))
1598 B - bit position
1600 h - bottom HI of an SI
1601 H - top HI of an SI
1602 q - bottom QI of an HI
1603 Q - top QI of an HI
1604 e - third QI of an SI (i.e. where the ES register gets values from)
1605 E - fourth QI of an SI (i.e. MSB)
1607 p - Add +0 to a zero-indexed HL based address.
1610 /* Implements the bulk of rl78_print_operand, below. We do it this
1611 way because we need to test for a constant at the top level and
1612 insert the '#', but not test for it anywhere else as we recurse
1613 down into the operand. */
1614 static void
1615 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1617 int need_paren;
1619 switch (GET_CODE (op))
1621 case MEM:
1622 if (letter == 'A')
1623 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1624 else
1626 if (rl78_far_p (op))
1628 fprintf (file, "es:");
1629 if (GET_CODE (XEXP (op, 0)) == UNSPEC)
1630 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1632 if (letter == 'H')
1634 op = adjust_address (op, HImode, 2);
1635 letter = 0;
1637 if (letter == 'h')
1639 op = adjust_address (op, HImode, 0);
1640 letter = 0;
1642 if (letter == 'Q')
1644 op = adjust_address (op, QImode, 1);
1645 letter = 0;
1647 if (letter == 'q')
1649 op = adjust_address (op, QImode, 0);
1650 letter = 0;
1652 if (letter == 'e')
1654 op = adjust_address (op, QImode, 2);
1655 letter = 0;
1657 if (letter == 'E')
1659 op = adjust_address (op, QImode, 3);
1660 letter = 0;
1662 if (CONSTANT_P (XEXP (op, 0)))
1664 if (!rl78_saddr_p (op))
1665 fprintf (file, "!");
1666 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1668 else if (GET_CODE (XEXP (op, 0)) == PLUS
1669 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1671 if (!rl78_saddr_p (op))
1672 fprintf (file, "!");
1673 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1675 else if (GET_CODE (XEXP (op, 0)) == PLUS
1676 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1677 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1679 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1680 fprintf (file, "[");
1681 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1682 if (letter == 'p' && GET_CODE (XEXP (op, 0)) == REG)
1683 fprintf (file, "+0");
1684 fprintf (file, "]");
1686 else
1688 op = XEXP (op, 0);
1689 fprintf (file, "[");
1690 rl78_print_operand_1 (file, op, letter);
1691 if (letter == 'p' && REG_P (op) && REGNO (op) == 6)
1692 fprintf (file, "+0");
1693 fprintf (file, "]");
1696 break;
1698 case REG:
1699 if (letter == 'Q')
1700 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1701 else if (letter == 'H')
1702 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1703 else if (letter == 'q')
1704 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1705 else if (letter == 'e')
1706 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1707 else if (letter == 'E')
1708 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1709 else if (letter == 'S')
1710 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1711 else if (GET_MODE (op) == HImode
1712 && ! (REGNO (op) & ~0xfe))
1714 if (letter == 'v')
1715 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1716 else
1717 fprintf (file, "%s", word_regnames [REGNO (op)]);
1719 else
1720 fprintf (file, "%s", reg_names [REGNO (op)]);
1721 break;
1723 case CONST_INT:
1724 if (letter == 'Q')
1725 fprintf (file, "%ld", INTVAL (op) >> 8);
1726 else if (letter == 'H')
1727 fprintf (file, "%ld", INTVAL (op) >> 16);
1728 else if (letter == 'q')
1729 fprintf (file, "%ld", INTVAL (op) & 0xff);
1730 else if (letter == 'h')
1731 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1732 else if (letter == 'e')
1733 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1734 else if (letter == 'B')
1736 int ival = INTVAL (op);
1737 if (ival == -128)
1738 ival = 0x80;
1739 if (exact_log2 (ival) >= 0)
1740 fprintf (file, "%d", exact_log2 (ival));
1741 else
1742 fprintf (file, "%d", exact_log2 (~ival & 0xff));
1744 else if (letter == 'E')
1745 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1746 else if (letter == 'm')
1747 fprintf (file, "%ld", - INTVAL (op));
1748 else if (letter == 's')
1749 fprintf (file, "%ld", INTVAL (op) % 8);
1750 else if (letter == 'S')
1751 fprintf (file, "%ld", INTVAL (op) % 16);
1752 else if (letter == 'r')
1753 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1754 else if (letter == 'C')
1755 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1756 else
1757 fprintf (file, "%ld", INTVAL (op));
1758 break;
1760 case CONST:
1761 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1762 break;
1764 case ZERO_EXTRACT:
1766 int bits = INTVAL (XEXP (op, 1));
1767 int ofs = INTVAL (XEXP (op, 2));
1768 if (bits == 16 && ofs == 0)
1769 fprintf (file, "%%lo16(");
1770 else if (bits == 16 && ofs == 16)
1771 fprintf (file, "%%hi16(");
1772 else if (bits == 8 && ofs == 16)
1773 fprintf (file, "%%hi8(");
1774 else
1775 gcc_unreachable ();
1776 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1777 fprintf (file, ")");
1779 break;
1781 case ZERO_EXTEND:
1782 if (GET_CODE (XEXP (op, 0)) == REG)
1783 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1784 else
1785 print_rtl (file, op);
1786 break;
1788 case PLUS:
1789 need_paren = 0;
1790 if (letter == 'H')
1792 fprintf (file, "%%hi16(");
1793 need_paren = 1;
1794 letter = 0;
1796 if (letter == 'h')
1798 fprintf (file, "%%lo16(");
1799 need_paren = 1;
1800 letter = 0;
1802 if (letter == 'e')
1804 fprintf (file, "%%hi8(");
1805 need_paren = 1;
1806 letter = 0;
1808 if (letter == 'q' || letter == 'Q')
1809 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1811 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1813 if (GET_CODE (XEXP (op, 1)) == SYMBOL_REF
1814 && SYMBOL_REF_DECL (XEXP (op, 1))
1815 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 1))) == FUNCTION_DECL)
1817 fprintf (file, "%%code(");
1818 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 1), 0)));
1819 fprintf (file, "+");
1820 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1821 fprintf (file, ")");
1823 else
1825 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1826 fprintf (file, "+");
1827 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1830 else
1832 if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1833 && SYMBOL_REF_DECL (XEXP (op, 0))
1834 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op, 0))) == FUNCTION_DECL)
1836 fprintf (file, "%%code(");
1837 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op, 0), 0)));
1838 fprintf (file, "+");
1839 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1840 fprintf (file, ")");
1842 else
1844 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1845 fprintf (file, "+");
1846 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1849 if (need_paren)
1850 fprintf (file, ")");
1851 break;
1853 case SUBREG:
1854 if (GET_MODE (op) == HImode
1855 && SUBREG_BYTE (op) == 0)
1857 fprintf (file, "%%lo16(");
1858 rl78_print_operand_1 (file, SUBREG_REG (op), 0);
1859 fprintf (file, ")");
1861 else if (GET_MODE (op) == HImode
1862 && SUBREG_BYTE (op) == 2)
1864 fprintf (file, "%%hi16(");
1865 rl78_print_operand_1 (file, SUBREG_REG (op), 0);
1866 fprintf (file, ")");
1868 else
1870 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1872 break;
1874 case SYMBOL_REF:
1875 need_paren = 0;
1876 if (letter == 'H')
1878 fprintf (file, "%%hi16(");
1879 need_paren = 1;
1880 letter = 0;
1882 if (letter == 'h')
1884 fprintf (file, "%%lo16(");
1885 need_paren = 1;
1886 letter = 0;
1888 if (letter == 'e')
1890 fprintf (file, "%%hi8(");
1891 need_paren = 1;
1892 letter = 0;
1894 if (letter == 'q' || letter == 'Q')
1895 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1897 if (SYMBOL_REF_DECL (op) && TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL)
1899 fprintf (file, "%%code(");
1900 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
1901 fprintf (file, ")");
1903 else
1904 assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0)));
1905 if (need_paren)
1906 fprintf (file, ")");
1907 break;
1909 case CODE_LABEL:
1910 case LABEL_REF:
1911 output_asm_label (op);
1912 break;
1914 case LTU:
1915 if (letter == 'z')
1916 fprintf (file, "#comparison eliminated");
1917 else
1918 fprintf (file, letter == 'C' ? "nc" : "c");
1919 break;
1920 case LEU:
1921 if (letter == 'z')
1922 fprintf (file, "br");
1923 else
1924 fprintf (file, letter == 'C' ? "h" : "nh");
1925 break;
1926 case GEU:
1927 if (letter == 'z')
1928 fprintf (file, "br");
1929 else
1930 fprintf (file, letter == 'C' ? "c" : "nc");
1931 break;
1932 case GTU:
1933 if (letter == 'z')
1934 fprintf (file, "#comparison eliminated");
1935 else
1936 fprintf (file, letter == 'C' ? "nh" : "h");
1937 break;
1938 case EQ:
1939 if (letter == 'z')
1940 fprintf (file, "br");
1941 else
1942 fprintf (file, letter == 'C' ? "nz" : "z");
1943 break;
1944 case NE:
1945 if (letter == 'z')
1946 fprintf (file, "#comparison eliminated");
1947 else
1948 fprintf (file, letter == 'C' ? "z" : "nz");
1949 break;
1951 /* Note: these assume appropriate adjustments were made so that
1952 unsigned comparisons, which is all this chip has, will
1953 work. */
1954 case LT:
1955 if (letter == 'z')
1956 fprintf (file, "#comparison eliminated");
1957 else
1958 fprintf (file, letter == 'C' ? "nc" : "c");
1959 break;
1960 case LE:
1961 if (letter == 'z')
1962 fprintf (file, "br");
1963 else
1964 fprintf (file, letter == 'C' ? "h" : "nh");
1965 break;
1966 case GE:
1967 if (letter == 'z')
1968 fprintf (file, "br");
1969 else
1970 fprintf (file, letter == 'C' ? "c" : "nc");
1971 break;
1972 case GT:
1973 if (letter == 'z')
1974 fprintf (file, "#comparison eliminated");
1975 else
1976 fprintf (file, letter == 'C' ? "nh" : "h");
1977 break;
1979 default:
1980 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1981 break;
1985 #undef TARGET_PRINT_OPERAND
1986 #define TARGET_PRINT_OPERAND rl78_print_operand
1988 static void
1989 rl78_print_operand (FILE * file, rtx op, int letter)
1991 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
1992 fprintf (file, "#");
1993 rl78_print_operand_1 (file, op, letter);
1996 #undef TARGET_TRAMPOLINE_INIT
1997 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1999 /* Note that the RL78's addressing makes it very difficult to do
2000 trampolines on the stack. So, libgcc has a small pool of
2001 trampolines from which one is allocated to this task. */
2002 static void
2003 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
2005 rtx mov_addr, thunk_addr;
2006 rtx function = XEXP (DECL_RTL (fndecl), 0);
2008 mov_addr = adjust_address (m_tramp, HImode, 0);
2009 thunk_addr = gen_reg_rtx (HImode);
2011 function = force_reg (HImode, function);
2012 static_chain = force_reg (HImode, static_chain);
2014 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
2015 emit_move_insn (mov_addr, thunk_addr);
2017 cfun->machine->trampolines_used = 1;
2020 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2021 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2023 static rtx
2024 rl78_trampoline_adjust_address (rtx m_tramp)
2026 rtx x = gen_rtx_MEM (HImode, m_tramp);
2027 return x;
2030 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2031 the "normal" compares, specifically, it only has unsigned compares,
2032 so we must synthesize the missing ones. */
2033 void
2034 rl78_expand_compare (rtx *operands)
2036 if (GET_CODE (operands[2]) == MEM)
2037 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
2042 /* Define this to 1 if you are debugging the peephole optimizers. */
2043 #define DEBUG_PEEP 0
2045 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2046 The default "word" size is a byte so we can effectively use all the
2047 registers, but we want to do 16-bit moves whenever possible. This
2048 function determines when such a move is an option. */
2049 bool
2050 rl78_peep_movhi_p (rtx *operands)
2052 int i;
2053 rtx m, a;
2055 /* (set (op0) (op1))
2056 (set (op2) (op3)) */
2058 if (! rl78_virt_insns_ok ())
2059 return false;
2061 #if DEBUG_PEEP
2062 fprintf (stderr, "\033[33m");
2063 debug_rtx (operands[0]);
2064 debug_rtx (operands[1]);
2065 debug_rtx (operands[2]);
2066 debug_rtx (operands[3]);
2067 fprintf (stderr, "\033[0m");
2068 #endif
2070 /* You can move a constant to memory as QImode, but not HImode. */
2071 if (GET_CODE (operands[0]) == MEM
2072 && GET_CODE (operands[1]) != REG)
2074 #if DEBUG_PEEP
2075 fprintf (stderr, "no peep: move constant to memory\n");
2076 #endif
2077 return false;
2080 if (rtx_equal_p (operands[0], operands[3]))
2082 #if DEBUG_PEEP
2083 fprintf (stderr, "no peep: overlapping\n");
2084 #endif
2085 return false;
2088 for (i = 0; i < 2; i ++)
2090 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
2092 #if DEBUG_PEEP
2093 fprintf (stderr, "no peep: different codes\n");
2094 #endif
2095 return false;
2097 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
2099 #if DEBUG_PEEP
2100 fprintf (stderr, "no peep: different modes\n");
2101 #endif
2102 return false;
2105 switch (GET_CODE (operands[i]))
2107 case REG:
2108 /* LSB MSB */
2109 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
2110 || GET_MODE (operands[i]) != QImode)
2112 #if DEBUG_PEEP
2113 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
2114 REGNO (operands[i]), REGNO (operands[i+2]),
2116 #endif
2117 return false;
2119 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
2121 #if DEBUG_PEEP
2122 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
2123 #endif
2124 return false;
2126 break;
2128 case CONST_INT:
2129 break;
2131 case MEM:
2132 if (GET_MODE (operands[i]) != QImode)
2133 return false;
2134 if (MEM_ALIGN (operands[i]) < 16)
2135 return false;
2136 a = XEXP (operands[i], 0);
2137 if (GET_CODE (a) == CONST)
2138 a = XEXP (a, 0);
2139 if (GET_CODE (a) == PLUS)
2140 a = XEXP (a, 1);
2141 if (GET_CODE (a) == CONST_INT
2142 && INTVAL (a) & 1)
2144 #if DEBUG_PEEP
2145 fprintf (stderr, "no peep: misaligned mem %d\n", i);
2146 debug_rtx (operands[i]);
2147 #endif
2148 return false;
2150 m = adjust_address (operands[i], QImode, 1);
2151 if (! rtx_equal_p (m, operands[i+2]))
2153 #if DEBUG_PEEP
2154 fprintf (stderr, "no peep: wrong mem %d\n", i);
2155 debug_rtx (m);
2156 debug_rtx (operands[i+2]);
2157 #endif
2158 return false;
2160 break;
2162 default:
2163 #if DEBUG_PEEP
2164 fprintf (stderr, "no peep: wrong rtx %d\n", i);
2165 #endif
2166 return false;
2169 #if DEBUG_PEEP
2170 fprintf (stderr, "\033[32mpeep!\033[0m\n");
2171 #endif
2172 return true;
2175 /* Likewise, when a peephole is activated, this function helps compute
2176 the new operands. */
2177 void
2178 rl78_setup_peep_movhi (rtx *operands)
2180 int i;
2182 for (i = 0; i < 2; i ++)
2184 switch (GET_CODE (operands[i]))
2186 case REG:
2187 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
2188 break;
2190 case CONST_INT:
2191 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
2192 break;
2194 case MEM:
2195 operands[i+4] = adjust_address (operands[i], HImode, 0);
2196 break;
2198 default:
2199 break;
2205 How Devirtualization works in the RL78 GCC port
2207 Background
2209 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2210 bytes of register space, in four banks, memory-mapped. One bank is
2211 the "selected" bank and holds the registers used for primary
2212 operations. Since the registers are memory mapped, often you can
2213 still refer to the unselected banks via memory accesses.
2215 Virtual Registers
2217 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2218 and refers to the other banks via their memory addresses, although
2219 they're treated as regular registers internally. These "virtual"
2220 registers are R8 through R23 (bank3 is reserved for asm-based
2221 interrupt handlers).
2223 There are four machine description files:
2225 rl78.md - common register-independent patterns and definitions
2226 rl78-expand.md - expanders
2227 rl78-virt.md - patterns that match BEFORE devirtualization
2228 rl78-real.md - patterns that match AFTER devirtualization
2230 At least through register allocation and reload, gcc is told that it
2231 can do pretty much anything - but may only use the virtual registers.
2232 GCC cannot properly create the varying addressing modes that the RL78
2233 supports in an efficient way.
2235 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2236 uses the "valloc" attribute in rl78-virt.md for determining the rules
2237 by which it will replace virtual registers with real registers (or
2238 not) and how to make up addressing modes. For example, insns tagged
2239 with "ro1" have a single read-only parameter, which may need to be
2240 moved from memory/constant/vreg to a suitable real register. As part
2241 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2242 patterns and enabling the rl78-real.md patterns. The new patterns'
2243 constraints are used to determine the real registers used. NOTE:
2244 patterns in rl78-virt.md essentially ignore the constrains and rely on
2245 predicates, where the rl78-real.md ones essentially ignore the
2246 predicates and rely on the constraints.
2248 The devirtualization pass is scheduled via the pass manager (despite
2249 being called "rl78_reorg") so it can be scheduled prior to var-track
2250 (the idea is to let gdb know about the new registers). Ideally, it
2251 would be scheduled right after pro/epilogue generation, so the
2252 post-reload optimizers could operate on the real registers, but when I
2253 tried that there were some issues building the target libraries.
2255 During devirtualization, a simple register move optimizer is run. It
2256 would be better to run a full CSE/propogation pass on it though, but
2257 that has not yet been attempted.
2260 #define DEBUG_ALLOC 0
2262 #define OP(x) (*recog_data.operand_loc[x])
2264 /* This array is used to hold knowledge about the contents of the
2265 real registers (A ... H), the memory-based registers (r8 ... r31)
2266 and the first NUM_STACK_LOCS words on the stack. We use this to
2267 avoid generating redundant move instructions.
2269 A value in the range 0 .. 31 indicates register A .. r31.
2270 A value in the range 32 .. 63 indicates stack slot (value - 32).
2271 A value of NOT_KNOWN indicates that the contents of that location
2272 are not known. */
2274 #define NUM_STACK_LOCS 32
2275 #define NOT_KNOWN 127
2277 static unsigned char content_memory [32 + NUM_STACK_LOCS];
2279 static unsigned char saved_update_index = NOT_KNOWN;
2280 static unsigned char saved_update_value;
2281 static machine_mode saved_update_mode;
2284 static inline void
2285 clear_content_memory (void)
2287 memset (content_memory, NOT_KNOWN, sizeof content_memory);
2288 if (dump_file)
2289 fprintf (dump_file, " clear content memory\n");
2290 saved_update_index = NOT_KNOWN;
2293 /* Convert LOC into an index into the content_memory array.
2294 If LOC cannot be converted, return NOT_KNOWN. */
2296 static unsigned char
2297 get_content_index (rtx loc)
2299 machine_mode mode;
2301 if (loc == NULL_RTX)
2302 return NOT_KNOWN;
2304 if (REG_P (loc))
2306 if (REGNO (loc) < 32)
2307 return REGNO (loc);
2308 return NOT_KNOWN;
2311 mode = GET_MODE (loc);
2313 if (! rl78_stack_based_mem (loc, mode))
2314 return NOT_KNOWN;
2316 loc = XEXP (loc, 0);
2318 if (REG_P (loc))
2319 /* loc = MEM (SP) */
2320 return 32;
2322 /* loc = MEM (PLUS (SP, INT)). */
2323 loc = XEXP (loc, 1);
2325 if (INTVAL (loc) < NUM_STACK_LOCS)
2326 return 32 + INTVAL (loc);
2328 return NOT_KNOWN;
2331 /* Return a string describing content INDEX in mode MODE.
2332 WARNING: Can return a pointer to a static buffer. */
2333 static const char *
2334 get_content_name (unsigned char index, machine_mode mode)
2336 static char buffer [128];
2338 if (index == NOT_KNOWN)
2339 return "Unknown";
2341 if (index > 31)
2342 sprintf (buffer, "stack slot %d", index - 32);
2343 else if (mode == HImode)
2344 sprintf (buffer, "%s%s",
2345 reg_names [index + 1], reg_names [index]);
2346 else
2347 return reg_names [index];
2349 return buffer;
2352 #if DEBUG_ALLOC
2354 static void
2355 display_content_memory (FILE * file)
2357 unsigned int i;
2359 fprintf (file, " Known memory contents:\n");
2361 for (i = 0; i < sizeof content_memory; i++)
2362 if (content_memory[i] != NOT_KNOWN)
2364 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2365 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2368 #endif
2370 static void
2371 update_content (unsigned char index, unsigned char val, machine_mode mode)
2373 unsigned int i;
2375 gcc_assert (index < sizeof content_memory);
2377 content_memory [index] = val;
2378 if (val != NOT_KNOWN)
2379 content_memory [val] = index;
2381 /* Make the entry in dump_file *before* VAL is increased below. */
2382 if (dump_file)
2384 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2385 if (val == NOT_KNOWN)
2386 fprintf (dump_file, "Unknown\n");
2387 else
2388 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2391 if (mode == HImode)
2393 val = val == NOT_KNOWN ? val : val + 1;
2395 content_memory [index + 1] = val;
2396 if (val != NOT_KNOWN)
2398 content_memory [val] = index + 1;
2399 -- val;
2403 /* Any other places that had INDEX recorded as their contents are now invalid. */
2404 for (i = 0; i < sizeof content_memory; i++)
2406 if (i == index
2407 || (val != NOT_KNOWN && i == val))
2409 if (mode == HImode)
2410 ++ i;
2411 continue;
2414 if (content_memory[i] == index
2415 || (val != NOT_KNOWN && content_memory[i] == val))
2417 content_memory[i] = NOT_KNOWN;
2419 if (dump_file)
2420 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2422 if (mode == HImode)
2423 content_memory[++ i] = NOT_KNOWN;
2428 /* Record that LOC contains VALUE.
2429 For HImode locations record that LOC+1 contains VALUE+1.
2430 If LOC is not a register or stack slot, do nothing.
2431 If VALUE is not a register or stack slot, clear the recorded content. */
2433 static void
2434 record_content (rtx loc, rtx value)
2436 machine_mode mode;
2437 unsigned char index;
2438 unsigned char val;
2440 if ((index = get_content_index (loc)) == NOT_KNOWN)
2441 return;
2443 val = get_content_index (value);
2445 mode = GET_MODE (loc);
2447 if (val == index)
2449 if (! optimize)
2450 return;
2452 /* This should not happen when optimizing. */
2453 #if 1
2454 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2455 get_content_name (val, mode));
2456 return;
2457 #else
2458 gcc_unreachable ();
2459 #endif
2462 update_content (index, val, mode);
2465 /* Returns TRUE if LOC already contains a copy of VALUE. */
2467 static bool
2468 already_contains (rtx loc, rtx value)
2470 unsigned char index;
2471 unsigned char val;
2473 if ((index = get_content_index (loc)) == NOT_KNOWN)
2474 return false;
2476 if ((val = get_content_index (value)) == NOT_KNOWN)
2477 return false;
2479 if (content_memory [index] != val)
2480 return false;
2482 if (GET_MODE (loc) == HImode)
2483 return content_memory [index + 1] == val + 1;
2485 return true;
2488 bool
2489 rl78_es_addr (rtx addr)
2491 if (GET_CODE (addr) == MEM)
2492 addr = XEXP (addr, 0);
2493 if (GET_CODE (addr) != UNSPEC)
2494 return false;
2495 if (XINT (addr, 1) != UNS_ES_ADDR)
2496 return false;
2497 return true;
2501 rl78_es_base (rtx addr)
2503 if (GET_CODE (addr) == MEM)
2504 addr = XEXP (addr, 0);
2505 addr = XVECEXP (addr, 0, 1);
2506 if (GET_CODE (addr) == CONST
2507 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2508 addr = XEXP (XEXP (addr, 0), 0);
2509 /* Mode doesn't matter here. */
2510 return gen_rtx_MEM (HImode, addr);
2513 /* Rescans an insn to see if it's recognized again. This is done
2514 carefully to ensure that all the constraint information is accurate
2515 for the newly matched insn. */
2516 static bool
2517 insn_ok_now (rtx_insn * insn)
2519 rtx pattern = PATTERN (insn);
2520 int i;
2522 INSN_CODE (insn) = -1;
2524 if (recog (pattern, insn, 0) > -1)
2526 extract_insn (insn);
2527 if (constrain_operands (1, get_preferred_alternatives (insn)))
2529 #if DEBUG_ALLOC
2530 fprintf (stderr, "\033[32m");
2531 debug_rtx (insn);
2532 fprintf (stderr, "\033[0m");
2533 #endif
2534 if (SET_P (pattern))
2535 record_content (SET_DEST (pattern), SET_SRC (pattern));
2537 /* We need to detect far addresses that haven't been
2538 converted to es/lo16 format. */
2539 for (i=0; i<recog_data.n_operands; i++)
2540 if (GET_CODE (OP (i)) == MEM
2541 && GET_MODE (XEXP (OP (i), 0)) == SImode
2542 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2543 return false;
2545 return true;
2548 else
2550 /* We need to re-recog the insn with virtual registers to get
2551 the operands. */
2552 cfun->machine->virt_insns_ok = 1;
2553 if (recog (pattern, insn, 0) > -1)
2555 extract_insn (insn);
2556 if (constrain_operands (0, get_preferred_alternatives (insn)))
2558 cfun->machine->virt_insns_ok = 0;
2559 return false;
2563 #if DEBUG_ALLOC
2564 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2565 debug_rtx (insn);
2566 #endif
2567 gcc_unreachable ();
2570 #if DEBUG_ALLOC
2571 fprintf (stderr, "\033[31m");
2572 debug_rtx (insn);
2573 fprintf (stderr, "\033[0m");
2574 #endif
2575 return false;
2578 #if DEBUG_ALLOC
2579 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2580 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2581 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2582 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2583 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2584 #else
2585 #define FAILED gcc_unreachable ()
2586 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2587 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2588 #endif
2590 /* Registers into which we move the contents of virtual registers. */
2591 #define X gen_rtx_REG (QImode, X_REG)
2592 #define A gen_rtx_REG (QImode, A_REG)
2593 #define C gen_rtx_REG (QImode, C_REG)
2594 #define B gen_rtx_REG (QImode, B_REG)
2595 #define E gen_rtx_REG (QImode, E_REG)
2596 #define D gen_rtx_REG (QImode, D_REG)
2597 #define L gen_rtx_REG (QImode, L_REG)
2598 #define H gen_rtx_REG (QImode, H_REG)
2600 #define AX gen_rtx_REG (HImode, AX_REG)
2601 #define BC gen_rtx_REG (HImode, BC_REG)
2602 #define DE gen_rtx_REG (HImode, DE_REG)
2603 #define HL gen_rtx_REG (HImode, HL_REG)
2605 /* Returns TRUE if R is a virtual register. */
2606 static inline bool
2607 is_virtual_register (rtx r)
2609 return (GET_CODE (r) == REG
2610 && REGNO (r) >= 8
2611 && REGNO (r) < 32);
2614 /* In all these alloc routines, we expect the following: the insn
2615 pattern is unshared, the insn was previously recognized and failed
2616 due to predicates or constraints, and the operand data is in
2617 recog_data. */
2619 static int virt_insn_was_frame;
2621 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2622 needed. */
2623 static rtx
2624 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2626 #if DEBUG_ALLOC
2627 fprintf (stderr, "\033[36m%d: ", line);
2628 debug_rtx (r);
2629 fprintf (stderr, "\033[0m");
2630 #endif
2631 /*SCHED_GROUP_P (r) = 1;*/
2632 if (virt_insn_was_frame)
2633 RTX_FRAME_RELATED_P (r) = 1;
2634 return r;
2637 #define EM(x) EM2 (__LINE__, x)
2639 /* Return a suitable RTX for the low half of a __far address. */
2640 static rtx
2641 rl78_lo16 (rtx addr)
2643 rtx r;
2645 if (GET_CODE (addr) == SYMBOL_REF
2646 || GET_CODE (addr) == CONST)
2648 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2649 r = gen_rtx_CONST (HImode, r);
2651 else
2652 r = rl78_subreg (HImode, addr, SImode, 0);
2654 r = gen_es_addr (r);
2655 cfun->machine->uses_es = true;
2657 return r;
2660 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2661 static rtx
2662 rl78_hi8 (rtx addr)
2664 if (GET_CODE (addr) == SYMBOL_REF
2665 || GET_CODE (addr) == CONST)
2667 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2668 r = gen_rtx_CONST (QImode, r);
2669 return r;
2671 return rl78_subreg (QImode, addr, SImode, 2);
2674 static void
2675 add_postponed_content_update (rtx to, rtx value)
2677 unsigned char index;
2679 if ((index = get_content_index (to)) == NOT_KNOWN)
2680 return;
2682 gcc_assert (saved_update_index == NOT_KNOWN);
2683 saved_update_index = index;
2684 saved_update_value = get_content_index (value);
2685 saved_update_mode = GET_MODE (to);
2688 static void
2689 process_postponed_content_update (void)
2691 if (saved_update_index != NOT_KNOWN)
2693 update_content (saved_update_index, saved_update_value, saved_update_mode);
2694 saved_update_index = NOT_KNOWN;
2698 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2699 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2700 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2701 BEFORE is true, FROM otherwise. */
2702 static rtx
2703 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2705 machine_mode mode = GET_MODE (to);
2707 if (optimize && before && already_contains (to, from))
2709 #if DEBUG_ALLOC
2710 display_content_memory (stderr);
2711 #endif
2712 if (dump_file)
2714 fprintf (dump_file, " Omit move of %s into ",
2715 get_content_name (get_content_index (from), mode));
2716 fprintf (dump_file, "%s as it already contains this value\n",
2717 get_content_name (get_content_index (to), mode));
2720 else
2722 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2724 EM (move);
2726 if (where == NULL_RTX)
2727 emit_insn (move);
2728 else if (before)
2729 emit_insn_before (move, where);
2730 else
2732 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2734 /* If necessary move REG_EH_REGION notes forward.
2735 cf. compiling gcc.dg/pr44545.c. */
2736 if (note != NULL_RTX)
2738 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2739 remove_note (where, note);
2742 emit_insn_after (move, where);
2745 if (before)
2746 record_content (to, from);
2747 else
2748 add_postponed_content_update (to, from);
2751 return before ? to : from;
2754 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2755 copy it into NEWBASE and return the updated MEM. Otherwise just
2756 return M. Any needed insns are emitted before BEFORE. */
2757 static rtx
2758 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2760 rtx base, index, addendr;
2761 int addend = 0;
2762 int need_es = 0;
2764 if (! MEM_P (m))
2765 return m;
2767 if (GET_MODE (XEXP (m, 0)) == SImode)
2769 rtx new_m;
2770 rtx seg = rl78_hi8 (XEXP (m, 0));
2772 if (!TARGET_ES0)
2774 emit_insn_before (EM (gen_movqi (A, seg)), before);
2775 emit_insn_before (EM (gen_movqi_to_es (A)), before);
2778 record_content (A, NULL_RTX);
2780 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2781 MEM_COPY_ATTRIBUTES (new_m, m);
2782 m = new_m;
2783 need_es = 1;
2786 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2787 gcc_assert (index == NULL_RTX);
2789 if (base == NULL_RTX)
2790 return m;
2792 if (addendr && GET_CODE (addendr) == CONST_INT)
2793 addend = INTVAL (addendr);
2795 gcc_assert (REG_P (base));
2796 gcc_assert (REG_P (newbase));
2798 int limit = 256 - GET_MODE_SIZE (GET_MODE (m));
2800 if (REGNO (base) == SP_REG)
2802 if (addend >= 0 && addend <= limit)
2803 return m;
2806 /* BASE should be a virtual register. We copy it to NEWBASE. If
2807 the addend is out of range for DE/HL, we use AX to compute the full
2808 address. */
2810 if (addend < 0
2811 || (addend > limit && REGNO (newbase) != BC_REG)
2812 || (addendr
2813 && (GET_CODE (addendr) != CONST_INT)
2814 && ((REGNO (newbase) != BC_REG))
2817 /* mov ax, vreg
2818 add ax, #imm
2819 mov hl, ax */
2820 EM (emit_insn_before (gen_movhi (AX, base), before));
2821 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2822 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2823 record_content (AX, NULL_RTX);
2824 record_content (newbase, NULL_RTX);
2826 base = newbase;
2827 addend = 0;
2828 addendr = 0;
2830 else
2832 base = gen_and_emit_move (newbase, base, before, true);
2835 if (addend)
2837 record_content (base, NULL_RTX);
2838 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2840 else if (addendr)
2842 record_content (base, NULL_RTX);
2843 base = gen_rtx_PLUS (HImode, base, addendr);
2846 if (need_es)
2848 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2849 cfun->machine->uses_es = true;
2851 else
2852 m = change_address (m, GET_MODE (m), base);
2853 return m;
2856 /* Copy SRC to accumulator (A or AX), placing any generated insns
2857 before BEFORE. Returns accumulator RTX. */
2858 static rtx
2859 move_to_acc (int opno, rtx before)
2861 rtx src = OP (opno);
2862 machine_mode mode = GET_MODE (src);
2864 if (REG_P (src) && REGNO (src) < 2)
2865 return src;
2867 if (mode == VOIDmode)
2868 mode = recog_data.operand_mode[opno];
2870 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2873 static void
2874 force_into_acc (rtx src, rtx before)
2876 machine_mode mode = GET_MODE (src);
2877 rtx move;
2879 if (REG_P (src) && REGNO (src) < 2)
2880 return;
2882 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2884 EM (move);
2886 emit_insn_before (move, before);
2887 record_content (AX, NULL_RTX);
2890 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2891 after AFTER. Returns accumulator RTX. */
2892 static rtx
2893 move_from_acc (unsigned int opno, rtx after)
2895 rtx dest = OP (opno);
2896 machine_mode mode = GET_MODE (dest);
2898 if (REG_P (dest) && REGNO (dest) < 2)
2899 return dest;
2901 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2904 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2905 before BEFORE. Returns reg RTX. */
2906 static rtx
2907 move_acc_to_reg (rtx acc, int regno, rtx before)
2909 machine_mode mode = GET_MODE (acc);
2910 rtx reg;
2912 reg = gen_rtx_REG (mode, regno);
2914 return gen_and_emit_move (reg, acc, before, true);
2917 /* Copy SRC to X, placing any generated insns before BEFORE.
2918 Returns X RTX. */
2919 static rtx
2920 move_to_x (int opno, rtx before)
2922 rtx src = OP (opno);
2923 machine_mode mode = GET_MODE (src);
2924 rtx reg;
2926 if (mode == VOIDmode)
2927 mode = recog_data.operand_mode[opno];
2928 reg = (mode == QImode) ? X : AX;
2930 if (mode == QImode || ! is_virtual_register (OP (opno)))
2932 OP (opno) = move_to_acc (opno, before);
2933 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
2934 return reg;
2937 return gen_and_emit_move (reg, src, before, true);
2940 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2941 Returns H/HL RTX. */
2942 static rtx
2943 move_to_hl (int opno, rtx before)
2945 rtx src = OP (opno);
2946 machine_mode mode = GET_MODE (src);
2947 rtx reg;
2949 if (mode == VOIDmode)
2950 mode = recog_data.operand_mode[opno];
2951 reg = (mode == QImode) ? L : HL;
2953 if (mode == QImode || ! is_virtual_register (OP (opno)))
2955 OP (opno) = move_to_acc (opno, before);
2956 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2957 return reg;
2960 return gen_and_emit_move (reg, src, before, true);
2963 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2964 Returns E/DE RTX. */
2965 static rtx
2966 move_to_de (int opno, rtx before)
2968 rtx src = OP (opno);
2969 machine_mode mode = GET_MODE (src);
2970 rtx reg;
2972 if (mode == VOIDmode)
2973 mode = recog_data.operand_mode[opno];
2975 reg = (mode == QImode) ? E : DE;
2977 if (mode == QImode || ! is_virtual_register (OP (opno)))
2979 OP (opno) = move_to_acc (opno, before);
2980 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2982 else
2984 gen_and_emit_move (reg, src, before, true);
2987 return reg;
2990 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2991 static void
2992 rl78_alloc_physical_registers_op1 (rtx_insn * insn)
2994 /* op[0] = func op[1] */
2996 /* We first try using A as the destination, then copying it
2997 back. */
2998 if (rtx_equal_p (OP (0), OP (1)))
3000 OP (0) =
3001 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3003 else
3005 /* If necessary, load the operands into BC and HL.
3006 Check to see if we already have OP (0) in HL
3007 and if so, swap the order.
3009 It is tempting to perform this optimization when OP(0) does
3010 not hold a MEM, but this leads to bigger code in general.
3011 The problem is that if OP(1) holds a MEM then swapping it
3012 into BC means a BC-relative load is used and these are 3
3013 bytes long vs 1 byte for an HL load. */
3014 if (MEM_P (OP (0))
3015 && already_contains (HL, XEXP (OP (0), 0)))
3017 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
3018 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
3020 else
3022 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3023 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3027 MAYBE_OK (insn);
3029 OP (0) = move_from_acc (0, insn);
3031 MAYBE_OK (insn);
3033 /* Try copying the src to acc first, then. This is for, for
3034 example, ZERO_EXTEND or NOT. */
3035 OP (1) = move_to_acc (1, insn);
3037 MUST_BE_OK (insn);
3040 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3041 Assumes that the current insn has already been recognised and hence the
3042 constraint data has been filled in. */
3043 static bool
3044 has_constraint (unsigned int opnum, enum constraint_num constraint)
3046 const char * p = recog_data.constraints[opnum];
3048 /* No constraints means anything is accepted. */
3049 if (p == NULL || *p == 0 || *p == ',')
3050 return true;
3054 char c;
3055 unsigned int len;
3057 c = *p;
3058 len = CONSTRAINT_LEN (c, p);
3059 gcc_assert (len > 0);
3061 switch (c)
3063 case 0:
3064 case ',':
3065 return false;
3066 default:
3067 if (lookup_constraint (p) == constraint)
3068 return true;
3070 p += len;
3072 while (1);
3075 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3076 static void
3077 rl78_alloc_physical_registers_op2 (rtx_insn * insn)
3079 rtx prev;
3080 rtx first;
3081 bool hl_used;
3082 int tmp_id;
3083 rtx saved_op1;
3085 if (rtx_equal_p (OP (0), OP (1)))
3087 if (MEM_P (OP (2)))
3089 OP (0) =
3090 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3091 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3093 else
3095 OP (0) =
3096 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
3097 OP (2) = transcode_memory_rtx (OP (2), DE, insn);
3100 else if (rtx_equal_p (OP (0), OP (2)))
3102 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3103 OP (0) =
3104 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3106 else
3108 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3109 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3110 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3113 MAYBE_OK (insn);
3115 prev = prev_nonnote_nondebug_insn (insn);
3116 if (recog_data.constraints[1][0] == '%'
3117 && is_virtual_register (OP (1))
3118 && ! is_virtual_register (OP (2))
3119 && ! CONSTANT_P (OP (2)))
3121 rtx tmp = OP (1);
3122 OP (1) = OP (2);
3123 OP (2) = tmp;
3126 /* Make a note of whether (H)L is being used. It matters
3127 because if OP (2) also needs reloading, then we must take
3128 care not to corrupt HL. */
3129 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
3131 /* If HL is not currently being used and dest == op1 then there are
3132 some possible optimizations available by reloading one of the
3133 operands into HL, before trying to use the accumulator. */
3134 if (optimize
3135 && ! hl_used
3136 && rtx_equal_p (OP (0), OP (1)))
3138 /* If op0 is a Ws1 type memory address then switching the base
3139 address register to HL might allow us to perform an in-memory
3140 operation. (eg for the INCW instruction).
3142 FIXME: Adding the move into HL is costly if this optimization is not
3143 going to work, so for now, make sure that we know that the new insn will
3144 match the requirements of the addhi3_real pattern. Really we ought to
3145 generate a candidate sequence, test that, and then install it if the
3146 results are good. */
3147 if (satisfies_constraint_Ws1 (OP (0))
3148 && has_constraint (0, CONSTRAINT_Wh1)
3149 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3151 rtx base, index, addend, newbase;
3153 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
3154 gcc_assert (index == NULL_RTX);
3155 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3157 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3158 if (addend != NULL_RTX)
3160 newbase = gen_and_emit_move (HL, base, insn, true);
3161 record_content (newbase, NULL_RTX);
3162 newbase = gen_rtx_PLUS (HImode, newbase, addend);
3164 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
3166 /* We do not want to fail here as this means that
3167 we have inserted useless insns into the stream. */
3168 MUST_BE_OK (insn);
3171 else if (REG_P (OP (0))
3172 && satisfies_constraint_Ws1 (OP (2))
3173 && has_constraint (2, CONSTRAINT_Wh1))
3175 rtx base, index, addend, newbase;
3177 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
3178 gcc_assert (index == NULL_RTX);
3179 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
3181 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3182 if (addend != NULL_RTX)
3184 gen_and_emit_move (HL, base, insn, true);
3186 if (REGNO (OP (0)) != X_REG)
3188 OP (1) = move_to_acc (1, insn);
3189 OP (0) = move_from_acc (0, insn);
3192 record_content (HL, NULL_RTX);
3193 newbase = gen_rtx_PLUS (HImode, HL, addend);
3195 OP (2) = change_address (OP (2), VOIDmode, newbase);
3197 /* We do not want to fail here as this means that
3198 we have inserted useless insns into the stream. */
3199 MUST_BE_OK (insn);
3204 OP (0) = move_from_acc (0, insn);
3206 tmp_id = get_max_insn_count ();
3207 saved_op1 = OP (1);
3209 if (rtx_equal_p (OP (1), OP (2)))
3210 OP (2) = OP (1) = move_to_acc (1, insn);
3211 else
3212 OP (1) = move_to_acc (1, insn);
3214 MAYBE_OK (insn);
3216 /* If we omitted the move of OP1 into the accumulator (because
3217 it was already there from a previous insn), then force the
3218 generation of the move instruction now. We know that we
3219 are about to emit a move into HL (or DE) via AX, and hence
3220 our optimization to remove the load of OP1 is no longer valid. */
3221 if (tmp_id == get_max_insn_count ())
3222 force_into_acc (saved_op1, insn);
3224 /* We have to copy op2 to HL (or DE), but that involves AX, which
3225 already has a live value. Emit it before those insns. */
3227 if (prev)
3228 first = next_nonnote_nondebug_insn (prev);
3229 else
3230 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3233 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
3235 MUST_BE_OK (insn);
3238 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3239 static void
3240 rl78_alloc_physical_registers_ro1 (rtx_insn * insn)
3242 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3244 MAYBE_OK (insn);
3246 OP (0) = move_to_acc (0, insn);
3248 MUST_BE_OK (insn);
3251 /* Devirtualize a compare insn. */
3252 static void
3253 rl78_alloc_physical_registers_cmp (rtx_insn * insn)
3255 int tmp_id;
3256 rtx saved_op1;
3257 rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3258 rtx first;
3260 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3261 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3263 /* HI compares have to have OP (1) in AX, but QI
3264 compares do not, so it is worth checking here. */
3265 MAYBE_OK (insn);
3267 /* For an HImode compare, OP (1) must always be in AX.
3268 But if OP (1) is a REG (and not AX), then we can avoid
3269 a reload of OP (1) if we reload OP (2) into AX and invert
3270 the comparison. */
3271 if (REG_P (OP (1))
3272 && REGNO (OP (1)) != AX_REG
3273 && GET_MODE (OP (1)) == HImode
3274 && MEM_P (OP (2)))
3276 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
3278 OP (2) = move_to_acc (2, insn);
3280 switch (GET_CODE (cmp))
3282 case EQ:
3283 case NE:
3284 break;
3285 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
3286 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
3287 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
3288 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
3290 case LT:
3291 case GT:
3292 case LE:
3293 case GE:
3294 #if DEBUG_ALLOC
3295 debug_rtx (insn);
3296 #endif
3297 default:
3298 gcc_unreachable ();
3301 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
3302 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
3303 else
3304 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
3306 MUST_BE_OK (insn);
3309 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3310 should be handled by the second alternative of the cbranchhi_real pattern. */
3311 if (rtx_equal_p (OP (1), OP (2)))
3313 OP (1) = OP (2) = BC;
3314 MUST_BE_OK (insn);
3317 tmp_id = get_max_insn_count ();
3318 saved_op1 = OP (1);
3320 OP (1) = move_to_acc (1, insn);
3322 MAYBE_OK (insn);
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 via AX, and hence our
3328 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);
3332 /* We have to copy op2 to HL, but that involves the acc, which
3333 already has a live value. Emit it before those insns. */
3334 if (prev)
3335 first = next_nonnote_nondebug_insn (prev);
3336 else
3337 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3339 OP (2) = move_to_hl (2, first);
3341 MUST_BE_OK (insn);
3344 /* Like op2, but AX = A * X. */
3345 static void
3346 rl78_alloc_physical_registers_umul (rtx_insn * insn)
3348 rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
3349 rtx first;
3350 int tmp_id;
3351 rtx saved_op1;
3353 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3354 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3355 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3357 MAYBE_OK (insn);
3359 if (recog_data.constraints[1][0] == '%'
3360 && is_virtual_register (OP (1))
3361 && !is_virtual_register (OP (2))
3362 && !CONSTANT_P (OP (2)))
3364 rtx tmp = OP (1);
3365 OP (1) = OP (2);
3366 OP (2) = tmp;
3369 OP (0) = move_from_acc (0, insn);
3371 tmp_id = get_max_insn_count ();
3372 saved_op1 = OP (1);
3374 if (rtx_equal_p (OP (1), OP (2)))
3376 gcc_assert (GET_MODE (OP (2)) == QImode);
3377 /* The MULU instruction does not support duplicate arguments
3378 but we know that if we copy OP (2) to X it will do so via
3379 A and thus OP (1) will already be loaded into A. */
3380 OP (2) = move_to_x (2, insn);
3381 OP (1) = A;
3383 else
3384 OP (1) = move_to_acc (1, insn);
3386 MAYBE_OK (insn);
3388 /* If we omitted the move of OP1 into the accumulator (because
3389 it was already there from a previous insn), then force the
3390 generation of the move instruction now. We know that we
3391 are about to emit a move into HL (or DE) via AX, and hence
3392 our optimization to remove the load of OP1 is no longer valid. */
3393 if (tmp_id == get_max_insn_count ())
3394 force_into_acc (saved_op1, insn);
3396 /* We have to copy op2 to X, but that involves the acc, which
3397 already has a live value. Emit it before those insns. */
3399 if (prev)
3400 first = next_nonnote_nondebug_insn (prev);
3401 else
3402 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3404 OP (2) = move_to_x (2, first);
3406 MUST_BE_OK (insn);
3409 static void
3410 rl78_alloc_address_registers_macax (rtx_insn * insn)
3412 int which, op;
3413 bool replace_in_op0 = false;
3414 bool replace_in_op1 = false;
3416 MAYBE_OK (insn);
3418 /* Two different MEMs are not allowed. */
3419 which = 0;
3420 for (op = 2; op >= 0; op --)
3422 if (MEM_P (OP (op)))
3424 if (op == 0 && replace_in_op0)
3425 continue;
3426 if (op == 1 && replace_in_op1)
3427 continue;
3429 switch (which)
3431 case 0:
3432 /* If we replace a MEM, make sure that we replace it for all
3433 occurrences of the same MEM in the insn. */
3434 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3435 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3437 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3438 if (op == 2
3439 && MEM_P (OP (op))
3440 && ((GET_CODE (XEXP (OP (op), 0)) == REG
3441 && REGNO (XEXP (OP (op), 0)) == SP_REG)
3442 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3443 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3445 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3446 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3448 if (replace_in_op0)
3449 OP (0) = OP (op);
3450 if (replace_in_op1)
3451 OP (1) = OP (op);
3452 break;
3453 case 1:
3454 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3455 break;
3456 case 2:
3457 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3458 break;
3460 which ++;
3464 MUST_BE_OK (insn);
3467 static void
3468 rl78_alloc_address_registers_div (rtx_insn * insn)
3470 MUST_BE_OK (insn);
3473 /* Scan all insns and devirtualize them. */
3474 static void
3475 rl78_alloc_physical_registers (void)
3477 /* During most of the compile, gcc is dealing with virtual
3478 registers. At this point, we need to assign physical registers
3479 to the vitual ones, and copy in/out as needed. */
3481 rtx_insn *insn, *curr;
3482 enum attr_valloc valloc_method;
3484 for (insn = get_insns (); insn; insn = curr)
3486 int i;
3488 curr = next_nonnote_nondebug_insn (insn);
3490 if (INSN_P (insn)
3491 && (GET_CODE (PATTERN (insn)) == SET
3492 || GET_CODE (PATTERN (insn)) == CALL)
3493 && INSN_CODE (insn) == -1)
3495 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3496 continue;
3497 i = recog (PATTERN (insn), insn, 0);
3498 if (i == -1)
3500 debug_rtx (insn);
3501 gcc_unreachable ();
3503 INSN_CODE (insn) = i;
3507 cfun->machine->virt_insns_ok = 0;
3508 cfun->machine->real_insns_ok = 1;
3510 clear_content_memory ();
3512 for (insn = get_insns (); insn; insn = curr)
3514 rtx pattern;
3516 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3518 if (!INSN_P (insn))
3520 if (LABEL_P (insn))
3521 clear_content_memory ();
3523 continue;
3526 if (dump_file)
3527 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3529 pattern = PATTERN (insn);
3530 if (GET_CODE (pattern) == PARALLEL)
3531 pattern = XVECEXP (pattern, 0, 0);
3532 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3533 clear_content_memory ();
3534 if (GET_CODE (pattern) != SET
3535 && GET_CODE (pattern) != CALL)
3536 continue;
3537 if (GET_CODE (pattern) == SET
3538 && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3539 continue;
3541 valloc_method = get_attr_valloc (insn);
3543 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3545 if (valloc_method == VALLOC_MACAX)
3547 record_content (AX, NULL_RTX);
3548 record_content (BC, NULL_RTX);
3549 record_content (DE, NULL_RTX);
3551 else if (valloc_method == VALLOC_DIVHI)
3553 record_content (AX, NULL_RTX);
3554 record_content (BC, NULL_RTX);
3556 else if (valloc_method == VALLOC_DIVSI)
3558 record_content (AX, NULL_RTX);
3559 record_content (BC, NULL_RTX);
3560 record_content (DE, NULL_RTX);
3561 record_content (HL, NULL_RTX);
3564 if (insn_ok_now (insn))
3565 continue;
3567 INSN_CODE (insn) = -1;
3569 if (RTX_FRAME_RELATED_P (insn))
3570 virt_insn_was_frame = 1;
3571 else
3572 virt_insn_was_frame = 0;
3574 switch (valloc_method)
3576 case VALLOC_OP1:
3577 rl78_alloc_physical_registers_op1 (insn);
3578 break;
3579 case VALLOC_OP2:
3580 rl78_alloc_physical_registers_op2 (insn);
3581 break;
3582 case VALLOC_RO1:
3583 rl78_alloc_physical_registers_ro1 (insn);
3584 break;
3585 case VALLOC_CMP:
3586 rl78_alloc_physical_registers_cmp (insn);
3587 break;
3588 case VALLOC_UMUL:
3589 rl78_alloc_physical_registers_umul (insn);
3590 record_content (AX, NULL_RTX);
3591 break;
3592 case VALLOC_MACAX:
3593 /* Macro that clobbers AX. */
3594 rl78_alloc_address_registers_macax (insn);
3595 record_content (AX, NULL_RTX);
3596 record_content (BC, NULL_RTX);
3597 record_content (DE, NULL_RTX);
3598 break;
3599 case VALLOC_DIVSI:
3600 rl78_alloc_address_registers_div (insn);
3601 record_content (AX, NULL_RTX);
3602 record_content (BC, NULL_RTX);
3603 record_content (DE, NULL_RTX);
3604 record_content (HL, NULL_RTX);
3605 break;
3606 case VALLOC_DIVHI:
3607 rl78_alloc_address_registers_div (insn);
3608 record_content (AX, NULL_RTX);
3609 record_content (BC, NULL_RTX);
3610 break;
3611 default:
3612 gcc_unreachable ();
3615 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3616 clear_content_memory ();
3617 else
3618 process_postponed_content_update ();
3621 #if DEBUG_ALLOC
3622 fprintf (stderr, "\033[0m");
3623 #endif
3626 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3627 This function scans for uses of registers; the last use (i.e. first
3628 encounter when scanning backwards) triggers a REG_DEAD note if the
3629 reg was previously in DEAD[]. */
3630 static void
3631 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3633 const char *fmt;
3634 int i, r;
3635 enum rtx_code code;
3637 if (!s)
3638 return;
3640 code = GET_CODE (s);
3642 switch (code)
3644 /* Compare registers by number. */
3645 case REG:
3646 r = REGNO (s);
3647 if (dump_file)
3649 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3650 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3651 print_rtl_single (dump_file, s);
3653 if (dead [r])
3654 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3655 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3656 dead [r + i] = 0;
3657 return;
3659 /* These codes have no constituent expressions
3660 and are unique. */
3661 case SCRATCH:
3662 case CC0:
3663 case PC:
3664 return;
3666 case CONST_INT:
3667 case CONST_VECTOR:
3668 case CONST_DOUBLE:
3669 case CONST_FIXED:
3670 /* These are kept unique for a given value. */
3671 return;
3673 default:
3674 break;
3677 fmt = GET_RTX_FORMAT (code);
3679 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3681 if (fmt[i] == 'E')
3683 int j;
3684 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3685 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3687 else if (fmt[i] == 'e')
3688 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3692 /* Like the previous function, but scan for SETs instead. */
3693 static void
3694 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3696 int r, i;
3698 if (GET_CODE (d) == MEM)
3699 rl78_note_reg_uses (dead, XEXP (d, 0), insn);
3701 if (GET_CODE (d) != REG)
3702 return;
3704 r = REGNO (d);
3705 if (dead [r])
3706 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3707 if (dump_file)
3708 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3709 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3710 dead [r + i] = 1;
3713 /* This is a rather crude register death pass. Death status is reset
3714 at every jump or call insn. */
3715 static void
3716 rl78_calculate_death_notes (void)
3718 char dead[FIRST_PSEUDO_REGISTER];
3719 rtx insn, p, s, d;
3720 int i;
3722 memset (dead, 0, sizeof (dead));
3724 for (insn = get_last_insn ();
3725 insn;
3726 insn = prev_nonnote_nondebug_insn (insn))
3728 if (dump_file)
3730 fprintf (dump_file, "\n--------------------------------------------------");
3731 fprintf (dump_file, "\nDead:");
3732 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3733 if (dead[i])
3734 fprintf (dump_file, " %s", reg_names[i]);
3735 fprintf (dump_file, "\n");
3736 print_rtl_single (dump_file, insn);
3739 switch (GET_CODE (insn))
3741 case INSN:
3742 p = PATTERN (insn);
3743 if (GET_CODE (p) == PARALLEL)
3745 rtx q = XVECEXP (p, 0 ,1);
3747 /* This happens with the DIV patterns. */
3748 if (GET_CODE (q) == SET)
3750 s = SET_SRC (q);
3751 d = SET_DEST (q);
3752 rl78_note_reg_set (dead, d, insn);
3753 rl78_note_reg_uses (dead, s, insn);
3756 p = XVECEXP (p, 0, 0);
3759 switch (GET_CODE (p))
3761 case SET:
3762 s = SET_SRC (p);
3763 d = SET_DEST (p);
3764 rl78_note_reg_set (dead, d, insn);
3765 rl78_note_reg_uses (dead, s, insn);
3766 break;
3768 case USE:
3769 rl78_note_reg_uses (dead, p, insn);
3770 break;
3772 default:
3773 break;
3775 break;
3777 case JUMP_INSN:
3778 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3780 memset (dead, 1, sizeof (dead));
3781 /* We expect a USE just prior to this, which will mark
3782 the actual return registers. The USE will have a
3783 death note, but we aren't going to be modifying it
3784 after this pass. */
3785 break;
3787 case CALL_INSN:
3788 memset (dead, 0, sizeof (dead));
3789 break;
3791 default:
3792 break;
3794 if (dump_file)
3795 print_rtl_single (dump_file, insn);
3799 /* Helper function to reset the origins in RP and the age in AGE for
3800 all registers. */
3801 static void
3802 reset_origins (int *rp, int *age)
3804 int i;
3805 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3807 rp[i] = i;
3808 age[i] = 0;
3812 static void
3813 set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
3815 rtx src = SET_SRC (pat);
3816 rtx dest = SET_DEST (pat);
3817 int mb = GET_MODE_SIZE (GET_MODE (dest));
3818 int i;
3820 if (GET_CODE (dest) == REG)
3822 int dr = REGNO (dest);
3824 if (GET_CODE (src) == REG)
3826 int sr = REGNO (src);
3827 bool same = true;
3828 int best_age, best_reg;
3830 /* See if the copy is not needed. */
3831 for (i = 0; i < mb; i ++)
3832 if (origins[dr + i] != origins[sr + i])
3833 same = false;
3835 if (same)
3837 if (dump_file)
3838 fprintf (dump_file, "deleting because dest already has correct value\n");
3839 delete_insn (insn);
3840 return;
3843 if (dr < 8 || sr >= 8)
3845 int ar;
3847 best_age = -1;
3848 best_reg = -1;
3850 /* See if the copy can be made from another
3851 bank 0 register instead, instead of the
3852 virtual src register. */
3853 for (ar = 0; ar < 8; ar += mb)
3855 same = true;
3857 for (i = 0; i < mb; i ++)
3858 if (origins[ar + i] != origins[sr + i])
3859 same = false;
3861 /* The chip has some reg-reg move limitations. */
3862 if (mb == 1 && dr > 3)
3863 same = false;
3865 if (same)
3867 if (best_age == -1 || best_age > age[sr + i])
3869 best_age = age[sr + i];
3870 best_reg = sr;
3875 if (best_reg != -1)
3877 /* FIXME: copy debug info too. */
3878 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3879 sr = best_reg;
3883 for (i = 0; i < mb; i++)
3885 origins[dr + i] = origins[sr + i];
3886 age[dr + i] = age[sr + i] + 1;
3889 else
3891 /* The destination is computed, its origin is itself. */
3892 if (dump_file)
3893 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3894 dr, mb, mb == 1 ? "" : "s");
3896 for (i = 0; i < mb; i ++)
3898 origins[dr + i] = dr + i;
3899 age[dr + i] = 0;
3903 /* Any registers marked with that reg as an origin are reset. */
3904 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3905 if (origins[i] >= dr && origins[i] < dr + mb)
3907 origins[i] = i;
3908 age[i] = 0;
3912 /* Special case - our MUL patterns uses AX and sometimes BC. */
3913 if (get_attr_valloc (insn) == VALLOC_MACAX)
3915 if (dump_file)
3916 fprintf (dump_file, "Resetting origin of AX/BC for MUL pattern.\n");
3918 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3919 if (i <= 3 || origins[i] <= 3)
3921 origins[i] = i;
3922 age[i] = 0;
3925 else if (get_attr_valloc (insn) == VALLOC_DIVHI)
3927 if (dump_file)
3928 fprintf (dump_file, "Resetting origin of AX/DE for DIVHI pattern.\n");
3930 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3931 if (i == A_REG
3932 || i == X_REG
3933 || i == D_REG
3934 || i == E_REG
3935 || origins[i] == A_REG
3936 || origins[i] == X_REG
3937 || origins[i] == D_REG
3938 || origins[i] == E_REG)
3940 origins[i] = i;
3941 age[i] = 0;
3944 else if (get_attr_valloc (insn) == VALLOC_DIVSI)
3946 if (dump_file)
3947 fprintf (dump_file, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
3949 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3950 if (i <= 7 || origins[i] <= 7)
3952 origins[i] = i;
3953 age[i] = 0;
3957 if (GET_CODE (src) == ASHIFT
3958 || GET_CODE (src) == ASHIFTRT
3959 || GET_CODE (src) == LSHIFTRT)
3961 rtx count = XEXP (src, 1);
3963 if (GET_CODE (count) == REG)
3965 /* Special case - our pattern clobbers the count register. */
3966 int r = REGNO (count);
3968 if (dump_file)
3969 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3971 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3972 if (i == r || origins[i] == r)
3974 origins[i] = i;
3975 age[i] = 0;
3981 /* The idea behind this optimization is to look for cases where we
3982 move data from A to B to C, and instead move from A to B, and A to
3983 C. If B is a virtual register or memory, this is a big win on its
3984 own. If B turns out to be unneeded after this, it's a bigger win.
3985 For each register, we try to determine where it's value originally
3986 came from, if it's propogated purely through moves (and not
3987 computes). The ORIGINS[] array has the regno for the "origin" of
3988 the value in the [regno] it's indexed by. */
3989 static void
3990 rl78_propogate_register_origins (void)
3992 int origins[FIRST_PSEUDO_REGISTER];
3993 int age[FIRST_PSEUDO_REGISTER];
3994 int i;
3995 rtx_insn *insn, *ninsn = NULL;
3996 rtx pat;
3998 reset_origins (origins, age);
4000 for (insn = get_insns (); insn; insn = ninsn)
4002 ninsn = next_nonnote_nondebug_insn (insn);
4004 if (dump_file)
4006 fprintf (dump_file, "\n");
4007 fprintf (dump_file, "Origins:");
4008 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
4009 if (origins[i] != i)
4010 fprintf (dump_file, " r%d=r%d", i, origins[i]);
4011 fprintf (dump_file, "\n");
4012 print_rtl_single (dump_file, insn);
4015 switch (GET_CODE (insn))
4017 case CODE_LABEL:
4018 case BARRIER:
4019 case CALL_INSN:
4020 case JUMP_INSN:
4021 reset_origins (origins, age);
4022 break;
4024 default:
4025 break;
4027 case INSN:
4028 pat = PATTERN (insn);
4030 if (GET_CODE (pat) == PARALLEL)
4032 rtx clobber = XVECEXP (pat, 0, 1);
4033 pat = XVECEXP (pat, 0, 0);
4034 if (GET_CODE (clobber) == CLOBBER
4035 && GET_CODE (XEXP (clobber, 0)) == REG)
4037 int cr = REGNO (XEXP (clobber, 0));
4038 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
4039 if (dump_file)
4040 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
4041 for (i = 0; i < mb; i++)
4043 origins[cr + i] = cr + i;
4044 age[cr + i] = 0;
4047 /* This happens with the DIV patterns. */
4048 else if (GET_CODE (clobber) == SET)
4050 set_origin (clobber, insn, origins, age);
4052 else
4053 break;
4056 if (GET_CODE (pat) == SET)
4058 set_origin (pat, insn, origins, age);
4060 else if (GET_CODE (pat) == CLOBBER
4061 && GET_CODE (XEXP (pat, 0)) == REG)
4063 if (REG_P (XEXP (pat, 0)))
4065 unsigned int reg = REGNO (XEXP (pat, 0));
4067 origins[reg] = reg;
4068 age[reg] = 0;
4075 /* Remove any SETs where the destination is unneeded. */
4076 static void
4077 rl78_remove_unused_sets (void)
4079 rtx_insn *insn, *ninsn = NULL;
4080 rtx dest;
4082 for (insn = get_insns (); insn; insn = ninsn)
4084 ninsn = next_nonnote_nondebug_insn (insn);
4086 rtx set = single_set (insn);
4087 if (set == NULL)
4088 continue;
4090 dest = SET_DEST (set);
4092 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
4093 continue;
4095 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
4097 if (dump_file)
4098 fprintf (dump_file, "deleting because the set register is never used.\n");
4099 delete_insn (insn);
4104 /* This is the top of the devritualization pass. */
4105 static void
4106 rl78_reorg (void)
4108 /* split2 only happens when optimizing, but we need all movSIs to be
4109 split now. */
4110 if (optimize <= 0)
4111 split_all_insns ();
4113 rl78_alloc_physical_registers ();
4115 if (dump_file)
4117 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4118 print_rtl_with_bb (dump_file, get_insns (), 0);
4121 rl78_propogate_register_origins ();
4122 rl78_calculate_death_notes ();
4124 if (dump_file)
4126 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4127 print_rtl_with_bb (dump_file, get_insns (), 0);
4128 fprintf (dump_file, "\n======================================================================\n");
4131 rl78_remove_unused_sets ();
4133 /* The code after devirtualizing has changed so much that at this point
4134 we might as well just rescan everything. Note that
4135 df_rescan_all_insns is not going to help here because it does not
4136 touch the artificial uses and defs. */
4137 df_finish_pass (true);
4138 if (optimize > 1)
4139 df_live_add_problem ();
4140 df_scan_alloc (NULL);
4141 df_scan_blocks ();
4143 if (optimize)
4144 df_analyze ();
4147 #undef TARGET_RETURN_IN_MEMORY
4148 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4150 static bool
4151 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4153 const HOST_WIDE_INT size = int_size_in_bytes (type);
4154 return (size == -1 || size > 8);
4158 #undef TARGET_RTX_COSTS
4159 #define TARGET_RTX_COSTS rl78_rtx_costs
4161 static bool
4162 rl78_rtx_costs (rtx x,
4163 int code,
4164 int outer_code ATTRIBUTE_UNUSED,
4165 int opno ATTRIBUTE_UNUSED,
4166 int * total,
4167 bool speed ATTRIBUTE_UNUSED)
4169 if (code == IF_THEN_ELSE)
4171 *total = COSTS_N_INSNS (10);
4172 return true;
4175 if (GET_MODE (x) == SImode)
4177 switch (code)
4179 case MULT:
4180 if (RL78_MUL_G14)
4181 *total = COSTS_N_INSNS (14);
4182 else if (RL78_MUL_G13)
4183 *total = COSTS_N_INSNS (29);
4184 else
4185 *total = COSTS_N_INSNS (500);
4186 return true;
4187 case PLUS:
4188 *total = COSTS_N_INSNS (8);
4189 return true;
4190 case ASHIFT:
4191 case ASHIFTRT:
4192 case LSHIFTRT:
4193 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4195 switch (INTVAL (XEXP (x, 1)))
4197 case 0: *total = COSTS_N_INSNS (0); break;
4198 case 1: *total = COSTS_N_INSNS (6); break;
4199 case 2: case 3: case 4: case 5: case 6: case 7:
4200 *total = COSTS_N_INSNS (10); break;
4201 case 8: *total = COSTS_N_INSNS (6); break;
4202 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4203 *total = COSTS_N_INSNS (10); break;
4204 case 16: *total = COSTS_N_INSNS (3); break;
4205 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4206 *total = COSTS_N_INSNS (4); break;
4207 case 24: *total = COSTS_N_INSNS (4); break;
4208 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4209 *total = COSTS_N_INSNS (5); break;
4212 else
4213 *total = COSTS_N_INSNS (10+4*16);
4214 return true;
4217 return false;
4221 static GTY(()) section * saddr_section;
4222 static GTY(()) section * frodata_section;
4225 rl78_saddr_p (rtx x)
4227 const char * c;
4229 if (MEM_P (x))
4230 x = XEXP (x, 0);
4231 if (GET_CODE (x) == PLUS)
4232 x = XEXP (x, 0);
4233 if (GET_CODE (x) != SYMBOL_REF)
4234 return 0;
4236 c = XSTR (x, 0);
4237 if (memcmp (c, "@s.", 3) == 0)
4238 return 1;
4240 return 0;
4244 rl78_sfr_p (rtx x)
4246 if (MEM_P (x))
4247 x = XEXP (x, 0);
4248 if (GET_CODE (x) != CONST_INT)
4249 return 0;
4251 if ((INTVAL (x) & 0xFF00) != 0xFF00)
4252 return 0;
4254 return 1;
4257 #undef TARGET_STRIP_NAME_ENCODING
4258 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4260 static const char *
4261 rl78_strip_name_encoding (const char * sym)
4263 while (1)
4265 if (*sym == '*')
4266 sym++;
4267 else if (*sym == '@' && sym[2] == '.')
4268 sym += 3;
4269 else
4270 return sym;
4274 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4275 is important if the stripped name is going to be passed to assemble_name()
4276 as that handles asterisk prefixed names in a special manner. */
4278 static const char *
4279 rl78_strip_nonasm_name_encoding (const char * sym)
4281 while (1)
4283 if (*sym == '@' && sym[2] == '.')
4284 sym += 3;
4285 else
4286 return sym;
4291 static int
4292 rl78_attrlist_to_encoding (tree list, tree decl ATTRIBUTE_UNUSED)
4294 while (list)
4296 if (is_attribute_p ("saddr", TREE_PURPOSE (list)))
4297 return 's';
4298 list = TREE_CHAIN (list);
4301 return 0;
4304 #define RL78_ATTRIBUTES(decl) \
4305 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4306 : DECL_ATTRIBUTES (decl) \
4307 ? (DECL_ATTRIBUTES (decl)) \
4308 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4310 #undef TARGET_ENCODE_SECTION_INFO
4311 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4313 static void
4314 rl78_encode_section_info (tree decl, rtx rtl, int first)
4316 rtx rtlname;
4317 const char * oldname;
4318 char encoding;
4319 char * newname;
4320 tree idp;
4321 tree type;
4322 tree rl78_attributes;
4324 if (!first)
4325 return;
4327 rtlname = XEXP (rtl, 0);
4329 if (GET_CODE (rtlname) == SYMBOL_REF)
4330 oldname = XSTR (rtlname, 0);
4331 else if (GET_CODE (rtlname) == MEM
4332 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
4333 oldname = XSTR (XEXP (rtlname, 0), 0);
4334 else
4335 gcc_unreachable ();
4337 type = TREE_TYPE (decl);
4338 if (type == error_mark_node)
4339 return;
4340 if (! DECL_P (decl))
4341 return;
4342 rl78_attributes = RL78_ATTRIBUTES (decl);
4344 encoding = rl78_attrlist_to_encoding (rl78_attributes, decl);
4346 if (encoding)
4348 newname = (char *) alloca (strlen (oldname) + 4);
4349 sprintf (newname, "@%c.%s", encoding, oldname);
4350 idp = get_identifier (newname);
4351 XEXP (rtl, 0) =
4352 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
4353 SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl);
4354 SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl);
4358 #undef TARGET_ASM_INIT_SECTIONS
4359 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4361 static void
4362 rl78_asm_init_sections (void)
4364 saddr_section
4365 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4366 "\t.section .saddr,\"aw\",@progbits");
4367 frodata_section
4368 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
4369 "\t.section .frodata,\"aw\",@progbits");
4372 #undef TARGET_ASM_SELECT_SECTION
4373 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4375 static section *
4376 rl78_select_section (tree decl,
4377 int reloc,
4378 unsigned HOST_WIDE_INT align)
4380 int readonly = 1;
4382 switch (TREE_CODE (decl))
4384 case VAR_DECL:
4385 if (!TREE_READONLY (decl)
4386 || TREE_SIDE_EFFECTS (decl)
4387 || !DECL_INITIAL (decl)
4388 || (DECL_INITIAL (decl) != error_mark_node
4389 && !TREE_CONSTANT (DECL_INITIAL (decl))))
4390 readonly = 0;
4391 break;
4392 case CONSTRUCTOR:
4393 if (! TREE_CONSTANT (decl))
4394 readonly = 0;
4395 break;
4397 default:
4398 break;
4401 if (TREE_CODE (decl) == VAR_DECL)
4403 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
4405 if (name[0] == '@' && name[2] == '.')
4406 switch (name[1])
4408 case 's':
4409 return saddr_section;
4412 if (TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_FAR
4413 && readonly)
4415 return frodata_section;
4419 if (readonly)
4420 return TARGET_ES0 ? frodata_section : readonly_data_section;
4422 switch (categorize_decl_for_section (decl, reloc))
4424 case SECCAT_TEXT: return text_section;
4425 case SECCAT_DATA: return data_section;
4426 case SECCAT_BSS: return bss_section;
4427 case SECCAT_RODATA: return TARGET_ES0 ? frodata_section : readonly_data_section;
4428 default:
4429 return default_select_section (decl, reloc, align);
4433 void
4434 rl78_output_labelref (FILE *file, const char *str)
4436 const char *str2;
4438 str2 = targetm.strip_name_encoding (str);
4439 if (str2[0] != '.')
4440 fputs (user_label_prefix, file);
4441 fputs (str2, file);
4444 void
4445 rl78_output_aligned_common (FILE *stream,
4446 tree decl ATTRIBUTE_UNUSED,
4447 const char *name,
4448 int size, int align, int global)
4450 /* We intentionally don't use rl78_section_tag() here. */
4451 if (name[0] == '@' && name[2] == '.')
4453 const char *sec = 0;
4454 switch (name[1])
4456 case 's':
4457 switch_to_section (saddr_section);
4458 sec = ".saddr";
4459 break;
4461 if (sec)
4463 const char *name2;
4464 int p2align = 0;
4466 while (align > BITS_PER_UNIT)
4468 align /= 2;
4469 p2align ++;
4471 name2 = targetm.strip_name_encoding (name);
4472 if (global)
4473 fprintf (stream, "\t.global\t_%s\n", name2);
4474 fprintf (stream, "\t.p2align %d\n", p2align);
4475 fprintf (stream, "\t.type\t_%s,@object\n", name2);
4476 fprintf (stream, "\t.size\t_%s,%d\n", name2, size);
4477 fprintf (stream, "_%s:\n\t.zero\t%d\n", name2, size);
4478 return;
4482 if (!global)
4484 fprintf (stream, "\t.local\t");
4485 assemble_name (stream, name);
4486 fprintf (stream, "\n");
4488 fprintf (stream, "\t.comm\t");
4489 assemble_name (stream, name);
4490 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
4493 #undef TARGET_INSERT_ATTRIBUTES
4494 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4496 static void
4497 rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
4499 if (TARGET_ES0
4500 && TREE_CODE (decl) == VAR_DECL
4501 && TREE_READONLY (decl)
4502 && TREE_ADDRESSABLE (decl)
4503 && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_GENERIC)
4505 tree type = TREE_TYPE (decl);
4506 tree attr = TYPE_ATTRIBUTES (type);
4507 int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR);
4509 TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
4513 #undef TARGET_ASM_INTEGER
4514 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4516 static bool
4517 rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
4519 if (default_assemble_integer (x, size, aligned_p))
4520 return true;
4522 if (size == 4)
4524 assemble_integer_with_op (".long\t", x);
4525 return true;
4528 return false;
4531 #undef TARGET_UNWIND_WORD_MODE
4532 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4534 static machine_mode
4535 rl78_unwind_word_mode (void)
4537 return HImode;
4540 #ifndef USE_COLLECT2
4541 #undef TARGET_ASM_CONSTRUCTOR
4542 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4543 #undef TARGET_ASM_DESTRUCTOR
4544 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4546 static void
4547 rl78_asm_ctor_dtor (rtx symbol, int priority, bool is_ctor)
4549 section *sec;
4551 if (priority != DEFAULT_INIT_PRIORITY)
4553 /* This section of the function is based upon code copied
4554 from: gcc/varasm.c:get_cdtor_priority_section(). */
4555 char buf[16];
4557 sprintf (buf, "%s.%.5u", is_ctor ? ".ctors" : ".dtors",
4558 MAX_INIT_PRIORITY - priority);
4559 sec = get_section (buf, 0, NULL);
4561 else
4562 sec = is_ctor ? ctors_section : dtors_section;
4564 assemble_addr_to_section (symbol, sec);
4567 static void
4568 rl78_asm_constructor (rtx symbol, int priority)
4570 rl78_asm_ctor_dtor (symbol, priority, true);
4573 static void
4574 rl78_asm_destructor (rtx symbol, int priority)
4576 rl78_asm_ctor_dtor (symbol, priority, false);
4578 #endif /* ! USE_COLLECT2 */
4580 /* Scan backwards through the insn chain looking to see if the flags
4581 have been set for a comparison of OP against OPERAND. Start with
4582 the insn *before* the current insn. */
4584 bool
4585 rl78_flags_already_set (rtx op, rtx operand)
4587 /* We only track the Z flag. */
4588 if (GET_CODE (op) != EQ && GET_CODE (op) != NE)
4589 return false;
4591 /* This should not happen, but let's be paranoid. */
4592 if (current_output_insn == NULL_RTX)
4593 return false;
4595 rtx_insn *insn;
4596 bool res = false;
4598 for (insn = prev_nonnote_nondebug_insn (current_output_insn);
4599 insn != NULL_RTX;
4600 insn = prev_nonnote_nondebug_insn (insn))
4602 if (LABEL_P (insn))
4603 break;
4605 if (! INSN_P (insn))
4606 continue;
4608 /* Make sure that the insn can be recognized. */
4609 if (recog_memoized (insn) == -1)
4610 continue;
4612 enum attr_update_Z updated = get_attr_update_Z (insn);
4614 rtx set = single_set (insn);
4615 bool must_break = (set != NULL_RTX && rtx_equal_p (operand, SET_DEST (set)));
4617 switch (updated)
4619 case UPDATE_Z_NO:
4620 break;
4621 case UPDATE_Z_CLOBBER:
4622 must_break = true;
4623 break;
4624 case UPDATE_Z_UPDATE_Z:
4625 res = must_break;
4626 must_break = true;
4627 break;
4628 default:
4629 gcc_unreachable ();
4632 if (must_break)
4633 break;
4636 /* We have to re-recognize the current insn as the call(s) to
4637 get_attr_update_Z() above will have overwritten the recog_data cache. */
4638 recog_memoized (current_output_insn);
4639 cleanup_subreg_operands (current_output_insn);
4640 constrain_operands_cached (current_output_insn, 1);
4642 return res;
4645 #undef TARGET_PREFERRED_RELOAD_CLASS
4646 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4648 static reg_class_t
4649 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
4651 if (rclass == NO_REGS)
4652 rclass = V_REGS;
4654 return rclass;
4658 struct gcc_target targetm = TARGET_INITIALIZER;
4660 #include "gt-rl78.h"