2014-12-19 Andrew MacLeod <amacleod@redhat.com>
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob5667b3268784120ecbc5a4f88ada5e370c3f9985
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2014 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 "tree.h"
26 #include "varasm.h"
27 #include "stor-layout.h"
28 #include "calls.h"
29 #include "rtl.h"
30 #include "regs.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "hashtab.h"
38 #include "hash-set.h"
39 #include "vec.h"
40 #include "machmode.h"
41 #include "input.h"
42 #include "function.h"
43 #include "expr.h"
44 #include "insn-codes.h"
45 #include "optabs.h"
46 #include "libfuncs.h"
47 #include "recog.h"
48 #include "diagnostic-core.h"
49 #include "toplev.h"
50 #include "reload.h"
51 #include "dominance.h"
52 #include "cfg.h"
53 #include "cfgrtl.h"
54 #include "cfganal.h"
55 #include "lcm.h"
56 #include "cfgbuild.h"
57 #include "cfgcleanup.h"
58 #include "predict.h"
59 #include "basic-block.h"
60 #include "df.h"
61 #include "ggc.h"
62 #include "tm_p.h"
63 #include "debug.h"
64 #include "target.h"
65 #include "target-def.h"
66 #include "langhooks.h"
67 #include "rl78-protos.h"
68 #include "dumpfile.h"
69 #include "tree-pass.h"
70 #include "context.h"
71 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
72 #include "insn-flags.h" /* for gen_*(). */
73 #include "builtins.h"
75 static inline bool is_interrupt_func (const_tree decl);
76 static inline bool is_brk_interrupt_func (const_tree decl);
77 static void rl78_reorg (void);
80 /* Debugging statements are tagged with DEBUG0 only so that they can
81 be easily enabled individually, by replacing the '0' with '1' as
82 needed. */
83 #define DEBUG0 0
84 #define DEBUG1 1
86 /* REGISTER_NAMES has the names for individual 8-bit registers, but
87 these have the names we need to use when referring to 16-bit
88 register pairs. */
89 static const char * const word_regnames[] =
91 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
92 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
93 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
94 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
95 "sp", "ap", "psw", "es", "cs"
98 struct GTY(()) machine_function
100 /* If set, the rest of the fields have been computed. */
101 int computed;
102 /* Which register pairs need to be pushed in the prologue. */
103 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
105 /* These fields describe the frame layout... */
106 /* arg pointer */
107 /* 4 bytes for saved PC */
108 int framesize_regs;
109 /* frame pointer */
110 int framesize_locals;
111 int framesize_outgoing;
112 /* stack pointer */
113 int framesize;
115 /* If set, recog is allowed to match against the "real" patterns. */
116 int real_insns_ok;
117 /* If set, recog is allowed to match against the "virtual" patterns. */
118 int virt_insns_ok;
119 /* Set if the current function needs to clean up any trampolines. */
120 int trampolines_used;
121 /* True if the ES register is used and hence
122 needs to be saved inside interrupt handlers. */
123 bool uses_es;
126 /* This is our init_machine_status, as set in
127 rl78_option_override. */
128 static struct machine_function *
129 rl78_init_machine_status (void)
131 struct machine_function *m;
133 m = ggc_cleared_alloc<machine_function> ();
134 m->virt_insns_ok = 1;
136 return m;
139 /* This pass converts virtual instructions using virtual registers, to
140 real instructions using real registers. Rather than run it as
141 reorg, we reschedule it before vartrack to help with debugging. */
142 namespace
144 const pass_data pass_data_rl78_devirt =
146 RTL_PASS, /* type */
147 "devirt", /* name */
148 OPTGROUP_NONE, /* optinfo_flags */
149 TV_MACH_DEP, /* tv_id */
150 0, /* properties_required */
151 0, /* properties_provided */
152 0, /* properties_destroyed */
153 0, /* todo_flags_start */
154 0, /* todo_flags_finish */
157 class pass_rl78_devirt : public rtl_opt_pass
159 public:
160 pass_rl78_devirt (gcc::context *ctxt)
161 : rtl_opt_pass (pass_data_rl78_devirt, ctxt)
165 /* opt_pass methods: */
166 virtual unsigned int execute (function *)
168 rl78_reorg ();
169 return 0;
172 } // anon namespace
174 rtl_opt_pass *
175 make_pass_rl78_devirt (gcc::context *ctxt)
177 return new pass_rl78_devirt (ctxt);
180 /* Redundant move elimination pass. Must be run after the basic block
181 reordering pass for the best effect. */
183 static unsigned int
184 move_elim_pass (void)
186 rtx_insn *insn, *ninsn;
187 rtx prev = NULL_RTX;
189 for (insn = get_insns (); insn; insn = ninsn)
191 rtx set;
193 ninsn = next_nonnote_nondebug_insn (insn);
195 if ((set = single_set (insn)) == NULL_RTX)
197 prev = NULL_RTX;
198 continue;
201 /* If we have two SET insns in a row (without anything
202 between them) and the source of the second one is the
203 destination of the first one, and vice versa, then we
204 can eliminate the second SET. */
205 if (prev
206 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
207 && rtx_equal_p (SET_DEST (set), SET_SRC (prev)))
209 if (dump_file)
210 fprintf (dump_file, " Delete insn %d because it is redundant\n",
211 INSN_UID (insn));
213 delete_insn (insn);
214 prev = NULL_RTX;
216 else
217 prev = set;
220 if (dump_file)
221 print_rtl_with_bb (dump_file, get_insns (), 0);
223 return 0;
226 namespace
228 const pass_data pass_data_rl78_move_elim =
230 RTL_PASS, /* type */
231 "move_elim", /* name */
232 OPTGROUP_NONE, /* optinfo_flags */
233 TV_MACH_DEP, /* tv_id */
234 0, /* properties_required */
235 0, /* properties_provided */
236 0, /* properties_destroyed */
237 0, /* todo_flags_start */
238 0, /* todo_flags_finish */
241 class pass_rl78_move_elim : public rtl_opt_pass
243 public:
244 pass_rl78_move_elim (gcc::context *ctxt)
245 : rtl_opt_pass (pass_data_rl78_move_elim, ctxt)
249 /* opt_pass methods: */
250 virtual unsigned int execute (function *) { return move_elim_pass (); }
252 } // anon namespace
254 rtl_opt_pass *
255 make_pass_rl78_move_elim (gcc::context *ctxt)
257 return new pass_rl78_move_elim (ctxt);
260 #undef TARGET_ASM_FILE_START
261 #define TARGET_ASM_FILE_START rl78_asm_file_start
263 static void
264 rl78_asm_file_start (void)
266 int i;
268 if (TARGET_G10)
270 /* The memory used is 0xffec8 to 0xffedf; real registers are in
271 0xffee0 to 0xffee7. */
272 for (i = 8; i < 32; i++)
273 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
275 else
277 for (i = 0; i < 8; i++)
279 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
280 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
281 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
285 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
286 struct register_pass_info rl78_devirt_info =
288 rl78_devirt_pass,
289 "pro_and_epilogue",
291 PASS_POS_INSERT_BEFORE
294 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
295 struct register_pass_info rl78_move_elim_info =
297 rl78_move_elim_pass,
298 "bbro",
300 PASS_POS_INSERT_AFTER
303 register_pass (& rl78_devirt_info);
304 register_pass (& rl78_move_elim_info);
308 #undef TARGET_OPTION_OVERRIDE
309 #define TARGET_OPTION_OVERRIDE rl78_option_override
311 static void
312 rl78_option_override (void)
314 flag_omit_frame_pointer = 1;
315 flag_no_function_cse = 1;
316 flag_split_wide_types = 0;
318 init_machine_status = rl78_init_machine_status;
320 if (TARGET_ALLREGS)
322 int i;
324 for (i = 24; i < 32; i++)
325 fixed_regs[i] = 0;
329 /* Most registers are 8 bits. Some are 16 bits because, for example,
330 gcc doesn't like dealing with $FP as a register pair (the second
331 half of $fp is also 2 to keep reload happy wrt register pairs, but
332 no register class includes it). This table maps register numbers
333 to size in bytes. */
334 static const int register_sizes[] =
336 1, 1, 1, 1, 1, 1, 1, 1,
337 1, 1, 1, 1, 1, 1, 1, 1,
338 1, 1, 1, 1, 1, 1, 2, 2,
339 1, 1, 1, 1, 1, 1, 1, 1,
340 2, 2, 1, 1, 1
343 /* Predicates used in the MD patterns. This one is true when virtual
344 insns may be matched, which typically means before (or during) the
345 devirt pass. */
346 bool
347 rl78_virt_insns_ok (void)
349 if (cfun)
350 return cfun->machine->virt_insns_ok;
351 return true;
354 /* Predicates used in the MD patterns. This one is true when real
355 insns may be matched, which typically means after (or during) the
356 devirt pass. */
357 bool
358 rl78_real_insns_ok (void)
360 if (cfun)
361 return cfun->machine->real_insns_ok;
362 return false;
365 /* Implements HARD_REGNO_NREGS. */
367 rl78_hard_regno_nregs (int regno, machine_mode mode)
369 int rs = register_sizes[regno];
370 if (rs < 1)
371 rs = 1;
372 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
375 /* Implements HARD_REGNO_MODE_OK. */
377 rl78_hard_regno_mode_ok (int regno, machine_mode mode)
379 int s = GET_MODE_SIZE (mode);
381 if (s < 1)
382 return 0;
383 /* These are not to be used by gcc. */
384 if (regno == 23 || regno == ES_REG || regno == CS_REG)
385 return 0;
386 /* $fp can always be accessed as a 16-bit value. */
387 if (regno == FP_REG && s == 2)
388 return 1;
389 if (regno < SP_REG)
391 /* Since a reg-reg move is really a reg-mem move, we must
392 enforce alignment. */
393 if (s > 1 && (regno % 2))
394 return 0;
395 return 1;
397 if (s == CC_REGNUM)
398 return (mode == BImode);
399 /* All other registers must be accessed in their natural sizes. */
400 if (s == register_sizes [regno])
401 return 1;
402 return 0;
405 /* Simplify_gen_subreg() doesn't handle memory references the way we
406 need it to below, so we use this function for when we must get a
407 valid subreg in a "natural" state. */
408 static rtx
409 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
411 if (GET_CODE (r) == MEM)
412 return adjust_address (r, mode, byte);
413 else
414 return simplify_gen_subreg (mode, r, omode, byte);
417 /* Used by movsi. Split SImode moves into two HImode moves, using
418 appropriate patterns for the upper and lower halves of symbols. */
419 void
420 rl78_expand_movsi (rtx *operands)
422 rtx op00, op02, op10, op12;
424 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
425 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
426 if (GET_CODE (operands[1]) == CONST
427 || GET_CODE (operands[1]) == SYMBOL_REF)
429 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
430 op10 = gen_rtx_CONST (HImode, op10);
431 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
432 op12 = gen_rtx_CONST (HImode, op12);
434 else
436 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
437 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
440 if (rtx_equal_p (operands[0], operands[1]))
442 else if (rtx_equal_p (op00, op12))
444 emit_move_insn (op02, op12);
445 emit_move_insn (op00, op10);
447 else
449 emit_move_insn (op00, op10);
450 emit_move_insn (op02, op12);
454 /* Generate code to move an SImode value. */
455 void
456 rl78_split_movsi (rtx *operands)
458 rtx op00, op02, op10, op12;
460 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
461 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
463 if (GET_CODE (operands[1]) == CONST
464 || GET_CODE (operands[1]) == SYMBOL_REF)
466 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
467 op10 = gen_rtx_CONST (HImode, op10);
468 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
469 op12 = gen_rtx_CONST (HImode, op12);
471 else
473 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
474 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
477 if (rtx_equal_p (operands[0], operands[1]))
479 else if (rtx_equal_p (op00, op12))
481 operands[2] = op02;
482 operands[4] = op12;
483 operands[3] = op00;
484 operands[5] = op10;
486 else
488 operands[2] = op00;
489 operands[4] = op10;
490 operands[3] = op02;
491 operands[5] = op12;
495 /* Used by various two-operand expanders which cannot accept all
496 operands in the "far" namespace. Force some such operands into
497 registers so that each pattern has at most one far operand. */
499 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
501 int did = 0;
502 rtx temp_reg = NULL;
504 /* FIXME: in the future, be smarter about only doing this if the
505 other operand is also far, assuming the devirtualizer can also
506 handle that. */
507 if (rl78_far_p (operands[0]))
509 temp_reg = operands[0];
510 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
511 did = 1;
513 if (!did)
514 return 0;
516 emit_insn (gen (operands[0], operands[1]));
517 if (temp_reg)
518 emit_move_insn (temp_reg, operands[0]);
519 return 1;
522 /* Likewise, but for three-operand expanders. */
524 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
526 int did = 0;
527 rtx temp_reg = NULL;
529 /* FIXME: Likewise. */
530 if (rl78_far_p (operands[1]))
532 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
533 emit_move_insn (temp_reg, operands[1]);
534 operands[1] = temp_reg;
535 did = 1;
537 if (rl78_far_p (operands[0]))
539 temp_reg = operands[0];
540 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
541 did = 1;
543 if (!did)
544 return 0;
546 emit_insn (gen (operands[0], operands[1], operands[2]));
547 if (temp_reg)
548 emit_move_insn (temp_reg, operands[0]);
549 return 1;
552 #undef TARGET_CAN_ELIMINATE
553 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
555 static bool
556 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
558 return true;
561 /* Returns true if the given register needs to be saved by the
562 current function. */
563 static bool
564 need_to_save (unsigned int regno)
566 if (is_interrupt_func (cfun->decl))
568 /* We don't know what devirt will need */
569 if (regno < 8)
570 return true;
572 /* We don't need to save registers that have
573 been reserved for interrupt handlers. */
574 if (regno > 23)
575 return false;
577 /* If the handler is a non-leaf function then it may call
578 non-interrupt aware routines which will happily clobber
579 any call_used registers, so we have to preserve them. */
580 if (!crtl->is_leaf && call_used_regs[regno])
581 return true;
583 /* Otherwise we only have to save a register, call_used
584 or not, if it is used by this handler. */
585 return df_regs_ever_live_p (regno);
588 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
589 return true;
590 if (fixed_regs[regno])
591 return false;
592 if (crtl->calls_eh_return)
593 return true;
594 if (df_regs_ever_live_p (regno)
595 && !call_used_regs[regno])
596 return true;
597 return false;
600 /* We use this to wrap all emitted insns in the prologue. */
601 static rtx
602 F (rtx x)
604 RTX_FRAME_RELATED_P (x) = 1;
605 return x;
608 /* Compute all the frame-related fields in our machine_function
609 structure. */
610 static void
611 rl78_compute_frame_info (void)
613 int i;
615 cfun->machine->computed = 1;
616 cfun->machine->framesize_regs = 0;
617 cfun->machine->framesize_locals = get_frame_size ();
618 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
620 for (i = 0; i < 16; i ++)
621 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
623 cfun->machine->need_to_push [i] = 1;
624 cfun->machine->framesize_regs += 2;
626 else
627 cfun->machine->need_to_push [i] = 0;
629 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
630 cfun->machine->framesize_locals ++;
632 cfun->machine->framesize = (cfun->machine->framesize_regs
633 + cfun->machine->framesize_locals
634 + cfun->machine->framesize_outgoing);
637 /* Returns true if the provided function has the specified attribute. */
638 static inline bool
639 has_func_attr (const_tree decl, const char * func_attr)
641 if (decl == NULL_TREE)
642 decl = current_function_decl;
644 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
647 /* Returns true if the provided function has the "interrupt" attribute. */
648 static inline bool
649 is_interrupt_func (const_tree decl)
651 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
654 /* Returns true if the provided function has the "brk_interrupt" attribute. */
655 static inline bool
656 is_brk_interrupt_func (const_tree decl)
658 return has_func_attr (decl, "brk_interrupt");
661 /* Check "interrupt" attributes. */
662 static tree
663 rl78_handle_func_attribute (tree * node,
664 tree name,
665 tree args,
666 int flags ATTRIBUTE_UNUSED,
667 bool * no_add_attrs)
669 gcc_assert (DECL_P (* node));
670 gcc_assert (args == NULL_TREE);
672 if (TREE_CODE (* node) != FUNCTION_DECL)
674 warning (OPT_Wattributes, "%qE attribute only applies to functions",
675 name);
676 * no_add_attrs = true;
679 /* FIXME: We ought to check that the interrupt and exception
680 handler attributes have been applied to void functions. */
681 return NULL_TREE;
684 #undef TARGET_ATTRIBUTE_TABLE
685 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
687 /* Table of RL78-specific attributes. */
688 const struct attribute_spec rl78_attribute_table[] =
690 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, decl_handler,
691 type_handler, affects_type_identity. */
692 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
693 NULL, false },
694 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
695 NULL, false },
696 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute,
697 NULL, false },
698 { NULL, 0, 0, false, false, false, NULL, NULL, false }
703 /* Break down an address RTX into its component base/index/addend
704 portions and return TRUE if the address is of a valid form, else
705 FALSE. */
706 static bool
707 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
709 *base = NULL_RTX;
710 *index = NULL_RTX;
711 *addend = NULL_RTX;
713 if (GET_CODE (x) == UNSPEC
714 && XINT (x, 1) == UNS_ES_ADDR)
715 x = XVECEXP (x, 0, 1);
717 if (GET_CODE (x) == REG)
719 *base = x;
720 return true;
723 /* We sometimes get these without the CONST wrapper */
724 if (GET_CODE (x) == PLUS
725 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
726 && GET_CODE (XEXP (x, 1)) == CONST_INT)
728 *addend = x;
729 return true;
732 if (GET_CODE (x) == PLUS)
734 *base = XEXP (x, 0);
735 x = XEXP (x, 1);
737 if (GET_CODE (*base) != REG
738 && GET_CODE (x) == REG)
740 rtx tmp = *base;
741 *base = x;
742 x = tmp;
745 if (GET_CODE (*base) != REG)
746 return false;
748 if (GET_CODE (x) == ZERO_EXTEND
749 && GET_CODE (XEXP (x, 0)) == REG)
751 *index = XEXP (x, 0);
752 return false;
756 switch (GET_CODE (x))
758 case PLUS:
759 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
760 && GET_CODE (XEXP (x, 0)) == CONST_INT)
762 *addend = x;
763 return true;
765 /* fall through */
766 case MEM:
767 case REG:
768 return false;
770 case CONST:
771 case SYMBOL_REF:
772 case CONST_INT:
773 *addend = x;
774 return true;
776 default:
777 return false;
780 return false;
783 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
784 addressing. */
785 bool
786 rl78_hl_b_c_addr_p (rtx op)
788 rtx hl, bc;
790 if (GET_CODE (op) != PLUS)
791 return false;
792 hl = XEXP (op, 0);
793 bc = XEXP (op, 1);
794 if (GET_CODE (hl) == ZERO_EXTEND)
796 rtx tmp = hl;
797 hl = bc;
798 bc = tmp;
800 if (GET_CODE (hl) != REG)
801 return false;
802 if (GET_CODE (bc) != ZERO_EXTEND)
803 return false;
804 bc = XEXP (bc, 0);
805 if (GET_CODE (bc) != REG)
806 return false;
807 if (REGNO (hl) != HL_REG)
808 return false;
809 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
810 return false;
812 return true;
815 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
817 /* Used in various constraints and predicates to match operands in the
818 "far" address space. */
820 rl78_far_p (rtx x)
822 if (! MEM_P (x))
823 return 0;
824 #if DEBUG0
825 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
826 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
827 #endif
828 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
831 /* Return the appropriate mode for a named address pointer. */
832 #undef TARGET_ADDR_SPACE_POINTER_MODE
833 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
835 static machine_mode
836 rl78_addr_space_pointer_mode (addr_space_t addrspace)
838 switch (addrspace)
840 case ADDR_SPACE_GENERIC:
841 return HImode;
842 case ADDR_SPACE_FAR:
843 return SImode;
844 default:
845 gcc_unreachable ();
849 /* Returns TRUE for valid addresses. */
850 #undef TARGET_VALID_POINTER_MODE
851 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
853 static bool
854 rl78_valid_pointer_mode (machine_mode m)
856 return (m == HImode || m == SImode);
859 /* Return the appropriate mode for a named address address. */
860 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
861 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
863 static machine_mode
864 rl78_addr_space_address_mode (addr_space_t addrspace)
866 switch (addrspace)
868 case ADDR_SPACE_GENERIC:
869 return HImode;
870 case ADDR_SPACE_FAR:
871 return SImode;
872 default:
873 gcc_unreachable ();
877 #undef TARGET_LEGITIMATE_CONSTANT_P
878 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
880 static bool
881 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
883 return true;
886 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
887 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
889 bool
890 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
891 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
893 rtx base, index, addend;
894 bool is_far_addr = false;
896 if (GET_CODE (x) == UNSPEC
897 && XINT (x, 1) == UNS_ES_ADDR)
899 x = XVECEXP (x, 0, 1);
900 is_far_addr = true;
903 if (as == ADDR_SPACE_GENERIC
904 && (GET_MODE (x) == SImode || is_far_addr))
905 return false;
907 if (! characterize_address (x, &base, &index, &addend))
908 return false;
910 /* We can't extract the high/low portions of a PLUS address
911 involving a register during devirtualization, so make sure all
912 such __far addresses do not have addends. This forces GCC to do
913 the sum separately. */
914 if (addend && base && as == ADDR_SPACE_FAR)
915 return false;
917 if (base && index)
919 int ir = REGNO (index);
920 int br = REGNO (base);
922 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
923 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
924 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
925 return false;
928 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
929 return false;
931 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
932 && REGNO (base) >= 8 && REGNO (base) <= 31)
933 return false;
935 return true;
938 /* Determine if one named address space is a subset of another. */
939 #undef TARGET_ADDR_SPACE_SUBSET_P
940 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
942 static bool
943 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
945 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
946 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
948 if (subset == superset)
949 return true;
951 else
952 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
955 #undef TARGET_ADDR_SPACE_CONVERT
956 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
958 /* Convert from one address space to another. */
959 static rtx
960 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
962 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
963 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
964 rtx result;
966 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
967 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
969 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
971 /* This is unpredictable, as we're truncating off usable address
972 bits. */
974 result = gen_reg_rtx (HImode);
975 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
976 return result;
978 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
980 /* This always works. */
981 result = gen_reg_rtx (SImode);
982 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
983 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
984 return result;
986 else
987 gcc_unreachable ();
990 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
991 bool
992 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
993 addr_space_t address_space ATTRIBUTE_UNUSED,
994 int outer_code ATTRIBUTE_UNUSED, int index_code)
996 if (regno <= SP_REG && regno >= 16)
997 return true;
998 if (index_code == REG)
999 return (regno == HL_REG);
1000 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
1001 return true;
1002 return false;
1005 /* Implements MODE_CODE_BASE_REG_CLASS. */
1006 enum reg_class
1007 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1008 addr_space_t address_space ATTRIBUTE_UNUSED,
1009 int outer_code ATTRIBUTE_UNUSED,
1010 int index_code ATTRIBUTE_UNUSED)
1012 return V_REGS;
1015 /* Typical stack layout should looks like this after the function's prologue:
1018 -- ^
1019 | | \ |
1020 | | arguments saved | Increasing
1021 | | on the stack | addresses
1022 PARENT arg pointer -> | | /
1023 -------------------------- ---- -------------------
1024 CHILD |ret | return address
1026 | | \
1027 | | call saved
1028 | | registers
1029 frame pointer -> | | /
1031 | | \
1032 | | local
1033 | | variables
1034 | | /
1036 | | \
1037 | | outgoing | Decreasing
1038 | | arguments | addresses
1039 current stack pointer -> | | / |
1040 -------------------------- ---- ------------------ V
1041 | | */
1043 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1044 described in the machine_Function struct definition, above. */
1046 rl78_initial_elimination_offset (int from, int to)
1048 int rv = 0; /* as if arg to arg */
1050 rl78_compute_frame_info ();
1052 switch (to)
1054 case STACK_POINTER_REGNUM:
1055 rv += cfun->machine->framesize_outgoing;
1056 rv += cfun->machine->framesize_locals;
1057 /* Fall through. */
1058 case FRAME_POINTER_REGNUM:
1059 rv += cfun->machine->framesize_regs;
1060 rv += 4;
1061 break;
1062 default:
1063 gcc_unreachable ();
1066 switch (from)
1068 case FRAME_POINTER_REGNUM:
1069 rv -= 4;
1070 rv -= cfun->machine->framesize_regs;
1071 case ARG_POINTER_REGNUM:
1072 break;
1073 default:
1074 gcc_unreachable ();
1077 return rv;
1080 static int
1081 rl78_is_naked_func (void)
1083 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1086 /* Expand the function prologue (from the prologue pattern). */
1087 void
1088 rl78_expand_prologue (void)
1090 int i, fs;
1091 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1092 int rb = 0;
1094 if (rl78_is_naked_func ())
1095 return;
1097 /* Always re-compute the frame info - the register usage may have changed. */
1098 rl78_compute_frame_info ();
1100 if (flag_stack_usage_info)
1101 current_function_static_stack_size = cfun->machine->framesize;
1103 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1104 for (i = 0; i < 4; i++)
1105 if (cfun->machine->need_to_push [i])
1107 /* Select Bank 0 if we are using any registers from Bank 0. */
1108 emit_insn (gen_sel_rb (GEN_INT (0)));
1109 break;
1112 for (i = 0; i < 16; i++)
1113 if (cfun->machine->need_to_push [i])
1115 if (TARGET_G10)
1117 if (i != 0)
1118 emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i * 2));
1119 F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
1121 else
1123 int need_bank = i/4;
1125 if (need_bank != rb)
1127 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1128 rb = need_bank;
1130 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
1134 if (rb != 0)
1135 emit_insn (gen_sel_rb (GEN_INT (0)));
1137 /* Save ES register inside interrupt functions if it is used. */
1138 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1140 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode, A_REG)));
1141 F (emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG))));
1144 if (frame_pointer_needed)
1146 F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1147 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
1148 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
1149 gen_rtx_REG (HImode, AX_REG)));
1152 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1153 while (fs > 0)
1155 int fs_byte = (fs > 254) ? 254 : fs;
1156 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1157 fs -= fs_byte;
1161 /* Expand the function epilogue (from the epilogue pattern). */
1162 void
1163 rl78_expand_epilogue (void)
1165 int i, fs;
1166 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1167 int rb = 0;
1169 if (rl78_is_naked_func ())
1170 return;
1172 if (frame_pointer_needed)
1174 emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1175 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1176 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
1177 gen_rtx_REG (HImode, AX_REG));
1179 else
1181 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1182 while (fs > 0)
1184 int fs_byte = (fs > 254) ? 254 : fs;
1186 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1187 fs -= fs_byte;
1191 if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
1193 emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
1194 emit_insn (gen_movqi_es (gen_rtx_REG (QImode, A_REG)));
1197 for (i = 15; i >= 0; i--)
1198 if (cfun->machine->need_to_push [i])
1200 rtx dest = gen_rtx_REG (HImode, i * 2);
1202 if (TARGET_G10)
1204 rtx ax = gen_rtx_REG (HImode, 0);
1206 emit_insn (gen_pop (ax));
1207 if (i != 0)
1209 emit_move_insn (dest, ax);
1210 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1211 emit_insn (gen_use (dest));
1214 else
1216 int need_bank = i / 4;
1218 if (need_bank != rb)
1220 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1221 rb = need_bank;
1223 emit_insn (gen_pop (dest));
1227 if (rb != 0)
1228 emit_insn (gen_sel_rb (GEN_INT (0)));
1230 if (cfun->machine->trampolines_used)
1231 emit_insn (gen_trampoline_uninit ());
1233 if (is_brk_interrupt_func (cfun->decl))
1234 emit_jump_insn (gen_brk_interrupt_return ());
1235 else if (is_interrupt_func (cfun->decl))
1236 emit_jump_insn (gen_interrupt_return ());
1237 else
1238 emit_jump_insn (gen_rl78_return ());
1241 /* Likewise, for exception handlers. */
1242 void
1243 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1245 /* FIXME - replace this with an indirect jump with stack adjust. */
1246 emit_jump_insn (gen_rl78_return ());
1249 #undef TARGET_ASM_FUNCTION_PROLOGUE
1250 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1252 /* We don't use this to actually emit the function prologue. We use
1253 this to insert a comment in the asm file describing the
1254 function. */
1255 static void
1256 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1258 int i;
1260 if (cfun->machine->framesize == 0)
1261 return;
1262 fprintf (file, "\t; start of function\n");
1264 if (cfun->machine->framesize_regs)
1266 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1267 for (i = 0; i < 16; i ++)
1268 if (cfun->machine->need_to_push[i])
1269 fprintf (file, " %s", word_regnames[i*2]);
1270 fprintf (file, "\n");
1273 if (frame_pointer_needed)
1274 fprintf (file, "\t; $fp points here (r22)\n");
1276 if (cfun->machine->framesize_locals)
1277 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1278 cfun->machine->framesize_locals == 1 ? "" : "s");
1280 if (cfun->machine->framesize_outgoing)
1281 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1282 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1284 if (cfun->machine->uses_es)
1285 fprintf (file, "\t; uses ES register\n");
1288 /* Return an RTL describing where a function return value of type RET_TYPE
1289 is held. */
1291 #undef TARGET_FUNCTION_VALUE
1292 #define TARGET_FUNCTION_VALUE rl78_function_value
1294 static rtx
1295 rl78_function_value (const_tree ret_type,
1296 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1297 bool outgoing ATTRIBUTE_UNUSED)
1299 machine_mode mode = TYPE_MODE (ret_type);
1301 return gen_rtx_REG (mode, 8);
1304 #undef TARGET_PROMOTE_FUNCTION_MODE
1305 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1307 static machine_mode
1308 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1309 machine_mode mode,
1310 int *punsignedp ATTRIBUTE_UNUSED,
1311 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1313 return mode;
1316 /* Return an RTL expression describing the register holding a function
1317 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1318 be passed on the stack. CUM describes the previous parameters to the
1319 function and NAMED is false if the parameter is part of a variable
1320 parameter list, or the last named parameter before the start of a
1321 variable parameter list. */
1323 #undef TARGET_FUNCTION_ARG
1324 #define TARGET_FUNCTION_ARG rl78_function_arg
1326 static rtx
1327 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1328 machine_mode mode ATTRIBUTE_UNUSED,
1329 const_tree type ATTRIBUTE_UNUSED,
1330 bool named ATTRIBUTE_UNUSED)
1332 return NULL_RTX;
1335 #undef TARGET_FUNCTION_ARG_ADVANCE
1336 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1338 static void
1339 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1340 bool named ATTRIBUTE_UNUSED)
1342 int rounded_size;
1343 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1345 rounded_size = ((mode == BLKmode)
1346 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1347 if (rounded_size & 1)
1348 rounded_size ++;
1349 (*cum) += rounded_size;
1352 #undef TARGET_FUNCTION_ARG_BOUNDARY
1353 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1355 static unsigned int
1356 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1357 const_tree type ATTRIBUTE_UNUSED)
1359 return 16;
1362 /* Supported modifier letters:
1364 A - address of a MEM
1365 S - SADDR form of a real register
1366 v - real register corresponding to a virtual register
1367 m - minus - negative of CONST_INT value.
1368 C - inverse of a conditional (NE vs EQ for example)
1369 C - complement of an integer
1370 z - collapsed conditional
1371 s - shift count mod 8
1372 S - shift count mod 16
1373 r - reverse shift count (8-(count mod 8))
1374 B - bit position
1376 h - bottom HI of an SI
1377 H - top HI of an SI
1378 q - bottom QI of an HI
1379 Q - top QI of an HI
1380 e - third QI of an SI (i.e. where the ES register gets values from)
1381 E - fourth QI of an SI (i.e. MSB)
1385 /* Implements the bulk of rl78_print_operand, below. We do it this
1386 way because we need to test for a constant at the top level and
1387 insert the '#', but not test for it anywhere else as we recurse
1388 down into the operand. */
1389 static void
1390 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1392 int need_paren;
1394 switch (GET_CODE (op))
1396 case MEM:
1397 if (letter == 'A')
1398 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1399 else
1401 if (rl78_far_p (op))
1403 fprintf (file, "es:");
1404 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1406 if (letter == 'H')
1408 op = adjust_address (op, HImode, 2);
1409 letter = 0;
1411 if (letter == 'h')
1413 op = adjust_address (op, HImode, 0);
1414 letter = 0;
1416 if (letter == 'Q')
1418 op = adjust_address (op, QImode, 1);
1419 letter = 0;
1421 if (letter == 'q')
1423 op = adjust_address (op, QImode, 0);
1424 letter = 0;
1426 if (letter == 'e')
1428 op = adjust_address (op, QImode, 2);
1429 letter = 0;
1431 if (letter == 'E')
1433 op = adjust_address (op, QImode, 3);
1434 letter = 0;
1436 if (CONSTANT_P (XEXP (op, 0)))
1438 fprintf (file, "!");
1439 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1441 else if (GET_CODE (XEXP (op, 0)) == PLUS
1442 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1444 fprintf (file, "!");
1445 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1447 else if (GET_CODE (XEXP (op, 0)) == PLUS
1448 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1449 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1451 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1452 fprintf (file, "[");
1453 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1454 fprintf (file, "]");
1456 else
1458 fprintf (file, "[");
1459 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1460 fprintf (file, "]");
1463 break;
1465 case REG:
1466 if (letter == 'Q')
1467 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1468 else if (letter == 'H')
1469 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1470 else if (letter == 'q')
1471 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1472 else if (letter == 'e')
1473 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1474 else if (letter == 'E')
1475 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1476 else if (letter == 'S')
1477 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1478 else if (GET_MODE (op) == HImode
1479 && ! (REGNO (op) & ~0xfe))
1481 if (letter == 'v')
1482 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1483 else
1484 fprintf (file, "%s", word_regnames [REGNO (op)]);
1486 else
1487 fprintf (file, "%s", reg_names [REGNO (op)]);
1488 break;
1490 case CONST_INT:
1491 if (letter == 'Q')
1492 fprintf (file, "%ld", INTVAL (op) >> 8);
1493 else if (letter == 'H')
1494 fprintf (file, "%ld", INTVAL (op) >> 16);
1495 else if (letter == 'q')
1496 fprintf (file, "%ld", INTVAL (op) & 0xff);
1497 else if (letter == 'h')
1498 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1499 else if (letter == 'e')
1500 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1501 else if (letter == 'B')
1502 fprintf (file, "%d", exact_log2 (INTVAL (op)));
1503 else if (letter == 'E')
1504 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1505 else if (letter == 'm')
1506 fprintf (file, "%ld", - INTVAL (op));
1507 else if (letter == 's')
1508 fprintf (file, "%ld", INTVAL (op) % 8);
1509 else if (letter == 'S')
1510 fprintf (file, "%ld", INTVAL (op) % 16);
1511 else if (letter == 'r')
1512 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1513 else if (letter == 'C')
1514 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1515 else
1516 fprintf (file, "%ld", INTVAL (op));
1517 break;
1519 case CONST:
1520 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1521 break;
1523 case ZERO_EXTRACT:
1525 int bits = INTVAL (XEXP (op, 1));
1526 int ofs = INTVAL (XEXP (op, 2));
1527 if (bits == 16 && ofs == 0)
1528 fprintf (file, "%%lo16(");
1529 else if (bits == 16 && ofs == 16)
1530 fprintf (file, "%%hi16(");
1531 else if (bits == 8 && ofs == 16)
1532 fprintf (file, "%%hi8(");
1533 else
1534 gcc_unreachable ();
1535 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1536 fprintf (file, ")");
1538 break;
1540 case ZERO_EXTEND:
1541 if (GET_CODE (XEXP (op, 0)) == REG)
1542 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1543 else
1544 print_rtl (file, op);
1545 break;
1547 case PLUS:
1548 need_paren = 0;
1549 if (letter == 'H')
1551 fprintf (file, "%%hi16(");
1552 need_paren = 1;
1553 letter = 0;
1555 if (letter == 'h')
1557 fprintf (file, "%%lo16(");
1558 need_paren = 1;
1559 letter = 0;
1561 if (letter == 'e')
1563 fprintf (file, "%%hi8(");
1564 need_paren = 1;
1565 letter = 0;
1567 if (letter == 'q' || letter == 'Q')
1568 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1570 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1572 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1573 fprintf (file, "+");
1574 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1576 else
1578 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1579 fprintf (file, "+");
1580 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1582 if (need_paren)
1583 fprintf (file, ")");
1584 break;
1586 case SYMBOL_REF:
1587 need_paren = 0;
1588 if (letter == 'H')
1590 fprintf (file, "%%hi16(");
1591 need_paren = 1;
1592 letter = 0;
1594 if (letter == 'h')
1596 fprintf (file, "%%lo16(");
1597 need_paren = 1;
1598 letter = 0;
1600 if (letter == 'e')
1602 fprintf (file, "%%hi8(");
1603 need_paren = 1;
1604 letter = 0;
1606 if (letter == 'q' || letter == 'Q')
1607 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1609 output_addr_const (file, op);
1610 if (need_paren)
1611 fprintf (file, ")");
1612 break;
1614 case CODE_LABEL:
1615 case LABEL_REF:
1616 output_asm_label (op);
1617 break;
1619 case LTU:
1620 if (letter == 'z')
1621 fprintf (file, "#comparison eliminated");
1622 else
1623 fprintf (file, letter == 'C' ? "nc" : "c");
1624 break;
1625 case LEU:
1626 if (letter == 'z')
1627 fprintf (file, "br");
1628 else
1629 fprintf (file, letter == 'C' ? "h" : "nh");
1630 break;
1631 case GEU:
1632 if (letter == 'z')
1633 fprintf (file, "br");
1634 else
1635 fprintf (file, letter == 'C' ? "c" : "nc");
1636 break;
1637 case GTU:
1638 if (letter == 'z')
1639 fprintf (file, "#comparison eliminated");
1640 else
1641 fprintf (file, letter == 'C' ? "nh" : "h");
1642 break;
1643 case EQ:
1644 if (letter == 'z')
1645 fprintf (file, "br");
1646 else
1647 fprintf (file, letter == 'C' ? "nz" : "z");
1648 break;
1649 case NE:
1650 if (letter == 'z')
1651 fprintf (file, "#comparison eliminated");
1652 else
1653 fprintf (file, letter == 'C' ? "z" : "nz");
1654 break;
1656 /* Note: these assume appropriate adjustments were made so that
1657 unsigned comparisons, which is all this chip has, will
1658 work. */
1659 case LT:
1660 if (letter == 'z')
1661 fprintf (file, "#comparison eliminated");
1662 else
1663 fprintf (file, letter == 'C' ? "nc" : "c");
1664 break;
1665 case LE:
1666 if (letter == 'z')
1667 fprintf (file, "br");
1668 else
1669 fprintf (file, letter == 'C' ? "h" : "nh");
1670 break;
1671 case GE:
1672 if (letter == 'z')
1673 fprintf (file, "br");
1674 else
1675 fprintf (file, letter == 'C' ? "c" : "nc");
1676 break;
1677 case GT:
1678 if (letter == 'z')
1679 fprintf (file, "#comparison eliminated");
1680 else
1681 fprintf (file, letter == 'C' ? "nh" : "h");
1682 break;
1684 default:
1685 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1686 break;
1690 #undef TARGET_PRINT_OPERAND
1691 #define TARGET_PRINT_OPERAND rl78_print_operand
1693 static void
1694 rl78_print_operand (FILE * file, rtx op, int letter)
1696 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
1697 fprintf (file, "#");
1698 rl78_print_operand_1 (file, op, letter);
1701 #undef TARGET_TRAMPOLINE_INIT
1702 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1704 /* Note that the RL78's addressing makes it very difficult to do
1705 trampolines on the stack. So, libgcc has a small pool of
1706 trampolines from which one is allocated to this task. */
1707 static void
1708 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1710 rtx mov_addr, thunk_addr;
1711 rtx function = XEXP (DECL_RTL (fndecl), 0);
1713 mov_addr = adjust_address (m_tramp, HImode, 0);
1714 thunk_addr = gen_reg_rtx (HImode);
1716 function = force_reg (HImode, function);
1717 static_chain = force_reg (HImode, static_chain);
1719 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1720 emit_move_insn (mov_addr, thunk_addr);
1722 cfun->machine->trampolines_used = 1;
1725 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1726 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1728 static rtx
1729 rl78_trampoline_adjust_address (rtx m_tramp)
1731 rtx x = gen_rtx_MEM (HImode, m_tramp);
1732 return x;
1735 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1736 the "normal" compares, specifically, it only has unsigned compares,
1737 so we must synthesize the missing ones. */
1738 void
1739 rl78_expand_compare (rtx *operands)
1741 if (GET_CODE (operands[2]) == MEM)
1742 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1747 /* Define this to 1 if you are debugging the peephole optimizers. */
1748 #define DEBUG_PEEP 0
1750 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1751 The default "word" size is a byte so we can effectively use all the
1752 registers, but we want to do 16-bit moves whenever possible. This
1753 function determines when such a move is an option. */
1754 bool
1755 rl78_peep_movhi_p (rtx *operands)
1757 int i;
1758 rtx m, a;
1760 /* (set (op0) (op1))
1761 (set (op2) (op3)) */
1763 if (! rl78_virt_insns_ok ())
1764 return false;
1766 #if DEBUG_PEEP
1767 fprintf (stderr, "\033[33m");
1768 debug_rtx (operands[0]);
1769 debug_rtx (operands[1]);
1770 debug_rtx (operands[2]);
1771 debug_rtx (operands[3]);
1772 fprintf (stderr, "\033[0m");
1773 #endif
1775 /* You can move a constant to memory as QImode, but not HImode. */
1776 if (GET_CODE (operands[0]) == MEM
1777 && GET_CODE (operands[1]) != REG)
1779 #if DEBUG_PEEP
1780 fprintf (stderr, "no peep: move constant to memory\n");
1781 #endif
1782 return false;
1785 if (rtx_equal_p (operands[0], operands[3]))
1787 #if DEBUG_PEEP
1788 fprintf (stderr, "no peep: overlapping\n");
1789 #endif
1790 return false;
1793 for (i = 0; i < 2; i ++)
1795 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1797 #if DEBUG_PEEP
1798 fprintf (stderr, "no peep: different codes\n");
1799 #endif
1800 return false;
1802 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1804 #if DEBUG_PEEP
1805 fprintf (stderr, "no peep: different modes\n");
1806 #endif
1807 return false;
1810 switch (GET_CODE (operands[i]))
1812 case REG:
1813 /* LSB MSB */
1814 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1815 || GET_MODE (operands[i]) != QImode)
1817 #if DEBUG_PEEP
1818 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1819 REGNO (operands[i]), REGNO (operands[i+2]),
1821 #endif
1822 return false;
1824 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1826 #if DEBUG_PEEP
1827 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1828 #endif
1829 return false;
1831 break;
1833 case CONST_INT:
1834 break;
1836 case MEM:
1837 if (GET_MODE (operands[i]) != QImode)
1838 return false;
1839 if (MEM_ALIGN (operands[i]) < 16)
1840 return false;
1841 a = XEXP (operands[i], 0);
1842 if (GET_CODE (a) == CONST)
1843 a = XEXP (a, 0);
1844 if (GET_CODE (a) == PLUS)
1845 a = XEXP (a, 1);
1846 if (GET_CODE (a) == CONST_INT
1847 && INTVAL (a) & 1)
1849 #if DEBUG_PEEP
1850 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1851 debug_rtx (operands[i]);
1852 #endif
1853 return false;
1855 m = adjust_address (operands[i], QImode, 1);
1856 if (! rtx_equal_p (m, operands[i+2]))
1858 #if DEBUG_PEEP
1859 fprintf (stderr, "no peep: wrong mem %d\n", i);
1860 debug_rtx (m);
1861 debug_rtx (operands[i+2]);
1862 #endif
1863 return false;
1865 break;
1867 default:
1868 #if DEBUG_PEEP
1869 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1870 #endif
1871 return false;
1874 #if DEBUG_PEEP
1875 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1876 #endif
1877 return true;
1880 /* Likewise, when a peephole is activated, this function helps compute
1881 the new operands. */
1882 void
1883 rl78_setup_peep_movhi (rtx *operands)
1885 int i;
1887 for (i = 0; i < 2; i ++)
1889 switch (GET_CODE (operands[i]))
1891 case REG:
1892 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1893 break;
1895 case CONST_INT:
1896 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
1897 break;
1899 case MEM:
1900 operands[i+4] = adjust_address (operands[i], HImode, 0);
1901 break;
1903 default:
1904 break;
1910 How Devirtualization works in the RL78 GCC port
1912 Background
1914 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1915 bytes of register space, in four banks, memory-mapped. One bank is
1916 the "selected" bank and holds the registers used for primary
1917 operations. Since the registers are memory mapped, often you can
1918 still refer to the unselected banks via memory accesses.
1920 Virtual Registers
1922 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1923 and refers to the other banks via their memory addresses, although
1924 they're treated as regular registers internally. These "virtual"
1925 registers are R8 through R23 (bank3 is reserved for asm-based
1926 interrupt handlers).
1928 There are four machine description files:
1930 rl78.md - common register-independent patterns and definitions
1931 rl78-expand.md - expanders
1932 rl78-virt.md - patterns that match BEFORE devirtualization
1933 rl78-real.md - patterns that match AFTER devirtualization
1935 At least through register allocation and reload, gcc is told that it
1936 can do pretty much anything - but may only use the virtual registers.
1937 GCC cannot properly create the varying addressing modes that the RL78
1938 supports in an efficient way.
1940 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1941 uses the "valloc" attribute in rl78-virt.md for determining the rules
1942 by which it will replace virtual registers with real registers (or
1943 not) and how to make up addressing modes. For example, insns tagged
1944 with "ro1" have a single read-only parameter, which may need to be
1945 moved from memory/constant/vreg to a suitable real register. As part
1946 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1947 patterns and enabling the rl78-real.md patterns. The new patterns'
1948 constraints are used to determine the real registers used. NOTE:
1949 patterns in rl78-virt.md essentially ignore the constrains and rely on
1950 predicates, where the rl78-real.md ones essentially ignore the
1951 predicates and rely on the constraints.
1953 The devirtualization pass is scheduled via the pass manager (despite
1954 being called "rl78_reorg") so it can be scheduled prior to var-track
1955 (the idea is to let gdb know about the new registers). Ideally, it
1956 would be scheduled right after pro/epilogue generation, so the
1957 post-reload optimizers could operate on the real registers, but when I
1958 tried that there were some issues building the target libraries.
1960 During devirtualization, a simple register move optimizer is run. It
1961 would be better to run a full CSE/propogation pass on it though, but
1962 that has not yet been attempted.
1965 #define DEBUG_ALLOC 0
1967 #define OP(x) (*recog_data.operand_loc[x])
1969 /* This array is used to hold knowledge about the contents of the
1970 real registers (A ... H), the memory-based registers (r8 ... r31)
1971 and the first NUM_STACK_LOCS words on the stack. We use this to
1972 avoid generating redundant move instructions.
1974 A value in the range 0 .. 31 indicates register A .. r31.
1975 A value in the range 32 .. 63 indicates stack slot (value - 32).
1976 A value of NOT_KNOWN indicates that the contents of that location
1977 are not known. */
1979 #define NUM_STACK_LOCS 32
1980 #define NOT_KNOWN 127
1982 static unsigned char content_memory [32 + NUM_STACK_LOCS];
1984 static unsigned char saved_update_index = NOT_KNOWN;
1985 static unsigned char saved_update_value;
1986 static machine_mode saved_update_mode;
1989 static inline void
1990 clear_content_memory (void)
1992 memset (content_memory, NOT_KNOWN, sizeof content_memory);
1993 if (dump_file)
1994 fprintf (dump_file, " clear content memory\n");
1995 saved_update_index = NOT_KNOWN;
1998 /* Convert LOC into an index into the content_memory array.
1999 If LOC cannot be converted, return NOT_KNOWN. */
2001 static unsigned char
2002 get_content_index (rtx loc)
2004 machine_mode mode;
2006 if (loc == NULL_RTX)
2007 return NOT_KNOWN;
2009 if (REG_P (loc))
2011 if (REGNO (loc) < 32)
2012 return REGNO (loc);
2013 return NOT_KNOWN;
2016 mode = GET_MODE (loc);
2018 if (! rl78_stack_based_mem (loc, mode))
2019 return NOT_KNOWN;
2021 loc = XEXP (loc, 0);
2023 if (REG_P (loc))
2024 /* loc = MEM (SP) */
2025 return 32;
2027 /* loc = MEM (PLUS (SP, INT)). */
2028 loc = XEXP (loc, 1);
2030 if (INTVAL (loc) < NUM_STACK_LOCS)
2031 return 32 + INTVAL (loc);
2033 return NOT_KNOWN;
2036 /* Return a string describing content INDEX in mode MODE.
2037 WARNING: Can return a pointer to a static buffer. */
2038 static const char *
2039 get_content_name (unsigned char index, machine_mode mode)
2041 static char buffer [128];
2043 if (index == NOT_KNOWN)
2044 return "Unknown";
2046 if (index > 31)
2047 sprintf (buffer, "stack slot %d", index - 32);
2048 else if (mode == HImode)
2049 sprintf (buffer, "%s%s",
2050 reg_names [index + 1], reg_names [index]);
2051 else
2052 return reg_names [index];
2054 return buffer;
2057 #if DEBUG_ALLOC
2059 static void
2060 display_content_memory (FILE * file)
2062 unsigned int i;
2064 fprintf (file, " Known memory contents:\n");
2066 for (i = 0; i < sizeof content_memory; i++)
2067 if (content_memory[i] != NOT_KNOWN)
2069 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2070 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2073 #endif
2075 static void
2076 update_content (unsigned char index, unsigned char val, machine_mode mode)
2078 unsigned int i;
2080 gcc_assert (index < sizeof content_memory);
2082 content_memory [index] = val;
2083 if (val != NOT_KNOWN)
2084 content_memory [val] = index;
2086 /* Make the entry in dump_file *before* VAL is increased below. */
2087 if (dump_file)
2089 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2090 if (val == NOT_KNOWN)
2091 fprintf (dump_file, "Unknown\n");
2092 else
2093 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2096 if (mode == HImode)
2098 val = val == NOT_KNOWN ? val : val + 1;
2100 content_memory [index + 1] = val;
2101 if (val != NOT_KNOWN)
2103 content_memory [val] = index + 1;
2104 -- val;
2108 /* Any other places that had INDEX recorded as their contents are now invalid. */
2109 for (i = 0; i < sizeof content_memory; i++)
2111 if (i == index
2112 || (val != NOT_KNOWN && i == val))
2114 if (mode == HImode)
2115 ++ i;
2116 continue;
2119 if (content_memory[i] == index
2120 || (val != NOT_KNOWN && content_memory[i] == val))
2122 content_memory[i] = NOT_KNOWN;
2124 if (dump_file)
2125 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2127 if (mode == HImode)
2128 content_memory[++ i] = NOT_KNOWN;
2133 /* Record that LOC contains VALUE.
2134 For HImode locations record that LOC+1 contains VALUE+1.
2135 If LOC is not a register or stack slot, do nothing.
2136 If VALUE is not a register or stack slot, clear the recorded content. */
2138 static void
2139 record_content (rtx loc, rtx value)
2141 machine_mode mode;
2142 unsigned char index;
2143 unsigned char val;
2145 if ((index = get_content_index (loc)) == NOT_KNOWN)
2146 return;
2148 val = get_content_index (value);
2150 mode = GET_MODE (loc);
2152 if (val == index)
2154 if (! optimize)
2155 return;
2157 /* This should not happen when optimizing. */
2158 #if 1
2159 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2160 get_content_name (val, mode));
2161 return;
2162 #else
2163 gcc_unreachable ();
2164 #endif
2167 update_content (index, val, mode);
2170 /* Returns TRUE if LOC already contains a copy of VALUE. */
2172 static bool
2173 already_contains (rtx loc, rtx value)
2175 unsigned char index;
2176 unsigned char val;
2178 if ((index = get_content_index (loc)) == NOT_KNOWN)
2179 return false;
2181 if ((val = get_content_index (value)) == NOT_KNOWN)
2182 return false;
2184 if (content_memory [index] != val)
2185 return false;
2187 if (GET_MODE (loc) == HImode)
2188 return content_memory [index + 1] == val + 1;
2190 return true;
2193 bool
2194 rl78_es_addr (rtx addr)
2196 if (GET_CODE (addr) == MEM)
2197 addr = XEXP (addr, 0);
2198 if (GET_CODE (addr) != UNSPEC)
2199 return false;
2200 if (XINT (addr, 1) != UNS_ES_ADDR)
2201 return false;
2202 return true;
2206 rl78_es_base (rtx addr)
2208 if (GET_CODE (addr) == MEM)
2209 addr = XEXP (addr, 0);
2210 addr = XVECEXP (addr, 0, 1);
2211 if (GET_CODE (addr) == CONST
2212 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2213 addr = XEXP (XEXP (addr, 0), 0);
2214 /* Mode doesn't matter here. */
2215 return gen_rtx_MEM (HImode, addr);
2218 /* Rescans an insn to see if it's recognized again. This is done
2219 carefully to ensure that all the constraint information is accurate
2220 for the newly matched insn. */
2221 static bool
2222 insn_ok_now (rtx_insn * insn)
2224 rtx pattern = PATTERN (insn);
2225 int i;
2227 INSN_CODE (insn) = -1;
2229 if (recog (pattern, insn, 0) > -1)
2231 extract_insn (insn);
2232 if (constrain_operands (1, get_preferred_alternatives (insn)))
2234 #if DEBUG_ALLOC
2235 fprintf (stderr, "\033[32m");
2236 debug_rtx (insn);
2237 fprintf (stderr, "\033[0m");
2238 #endif
2239 if (SET_P (pattern))
2240 record_content (SET_DEST (pattern), SET_SRC (pattern));
2242 /* We need to detect far addresses that haven't been
2243 converted to es/lo16 format. */
2244 for (i=0; i<recog_data.n_operands; i++)
2245 if (GET_CODE (OP (i)) == MEM
2246 && GET_MODE (XEXP (OP (i), 0)) == SImode
2247 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2248 return false;
2250 return true;
2253 else
2255 /* We need to re-recog the insn with virtual registers to get
2256 the operands. */
2257 cfun->machine->virt_insns_ok = 1;
2258 if (recog (pattern, insn, 0) > -1)
2260 extract_insn (insn);
2261 if (constrain_operands (0, get_preferred_alternatives (insn)))
2263 cfun->machine->virt_insns_ok = 0;
2264 return false;
2268 #if DEBUG_ALLOC
2269 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2270 debug_rtx (insn);
2271 #endif
2272 gcc_unreachable ();
2275 #if DEBUG_ALLOC
2276 fprintf (stderr, "\033[31m");
2277 debug_rtx (insn);
2278 fprintf (stderr, "\033[0m");
2279 #endif
2280 return false;
2283 #if DEBUG_ALLOC
2284 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2285 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2286 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2287 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2288 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2289 #else
2290 #define FAILED gcc_unreachable ()
2291 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2292 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2293 #endif
2295 /* Registers into which we move the contents of virtual registers. */
2296 #define X gen_rtx_REG (QImode, X_REG)
2297 #define A gen_rtx_REG (QImode, A_REG)
2298 #define C gen_rtx_REG (QImode, C_REG)
2299 #define B gen_rtx_REG (QImode, B_REG)
2300 #define E gen_rtx_REG (QImode, E_REG)
2301 #define D gen_rtx_REG (QImode, D_REG)
2302 #define L gen_rtx_REG (QImode, L_REG)
2303 #define H gen_rtx_REG (QImode, H_REG)
2305 #define AX gen_rtx_REG (HImode, AX_REG)
2306 #define BC gen_rtx_REG (HImode, BC_REG)
2307 #define DE gen_rtx_REG (HImode, DE_REG)
2308 #define HL gen_rtx_REG (HImode, HL_REG)
2310 /* Returns TRUE if R is a virtual register. */
2311 static inline bool
2312 is_virtual_register (rtx r)
2314 return (GET_CODE (r) == REG
2315 && REGNO (r) >= 8
2316 && REGNO (r) < 32);
2319 /* In all these alloc routines, we expect the following: the insn
2320 pattern is unshared, the insn was previously recognized and failed
2321 due to predicates or constraints, and the operand data is in
2322 recog_data. */
2324 static int virt_insn_was_frame;
2326 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2327 needed. */
2328 static rtx
2329 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2331 #if DEBUG_ALLOC
2332 fprintf (stderr, "\033[36m%d: ", line);
2333 debug_rtx (r);
2334 fprintf (stderr, "\033[0m");
2335 #endif
2336 /*SCHED_GROUP_P (r) = 1;*/
2337 if (virt_insn_was_frame)
2338 RTX_FRAME_RELATED_P (r) = 1;
2339 return r;
2342 #define EM(x) EM2 (__LINE__, x)
2344 /* Return a suitable RTX for the low half of a __far address. */
2345 static rtx
2346 rl78_lo16 (rtx addr)
2348 rtx r;
2350 if (GET_CODE (addr) == SYMBOL_REF
2351 || GET_CODE (addr) == CONST)
2353 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2354 r = gen_rtx_CONST (HImode, r);
2356 else
2357 r = rl78_subreg (HImode, addr, SImode, 0);
2359 r = gen_es_addr (r);
2360 cfun->machine->uses_es = true;
2362 return r;
2365 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2366 static rtx
2367 rl78_hi8 (rtx addr)
2369 if (GET_CODE (addr) == SYMBOL_REF
2370 || GET_CODE (addr) == CONST)
2372 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2373 r = gen_rtx_CONST (QImode, r);
2374 return r;
2376 return rl78_subreg (QImode, addr, SImode, 2);
2379 static void
2380 add_postponed_content_update (rtx to, rtx value)
2382 unsigned char index;
2384 if ((index = get_content_index (to)) == NOT_KNOWN)
2385 return;
2387 gcc_assert (saved_update_index == NOT_KNOWN);
2388 saved_update_index = index;
2389 saved_update_value = get_content_index (value);
2390 saved_update_mode = GET_MODE (to);
2393 static void
2394 process_postponed_content_update (void)
2396 if (saved_update_index != NOT_KNOWN)
2398 update_content (saved_update_index, saved_update_value, saved_update_mode);
2399 saved_update_index = NOT_KNOWN;
2403 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2404 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2405 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2406 BEFORE is true, FROM otherwise. */
2407 static rtx
2408 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2410 machine_mode mode = GET_MODE (to);
2412 if (optimize && before && already_contains (to, from))
2414 #if DEBUG_ALLOC
2415 display_content_memory (stderr);
2416 #endif
2417 if (dump_file)
2419 fprintf (dump_file, " Omit move of %s into ",
2420 get_content_name (get_content_index (from), mode));
2421 fprintf (dump_file, "%s as it already contains this value\n",
2422 get_content_name (get_content_index (to), mode));
2425 else
2427 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2429 EM (move);
2431 if (where == NULL_RTX)
2432 emit_insn (move);
2433 else if (before)
2434 emit_insn_before (move, where);
2435 else
2437 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2439 /* If necessary move REG_EH_REGION notes forward.
2440 cf. compiling gcc.dg/pr44545.c. */
2441 if (note != NULL_RTX)
2443 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2444 remove_note (where, note);
2447 emit_insn_after (move, where);
2450 if (before)
2451 record_content (to, from);
2452 else
2453 add_postponed_content_update (to, from);
2456 return before ? to : from;
2459 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2460 copy it into NEWBASE and return the updated MEM. Otherwise just
2461 return M. Any needed insns are emitted before BEFORE. */
2462 static rtx
2463 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2465 rtx base, index, addendr;
2466 int addend = 0;
2467 int need_es = 0;
2469 if (! MEM_P (m))
2470 return m;
2472 if (GET_MODE (XEXP (m, 0)) == SImode)
2474 rtx new_m;
2475 rtx seg = rl78_hi8 (XEXP (m, 0));
2477 #if DEBUG_ALLOC
2478 fprintf (stderr, "setting ES:\n");
2479 debug_rtx(seg);
2480 #endif
2481 emit_insn_before (EM (gen_movqi (A, seg)), before);
2482 emit_insn_before (EM (gen_movqi_es (A)), before);
2483 record_content (A, NULL_RTX);
2485 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2486 MEM_COPY_ATTRIBUTES (new_m, m);
2487 m = new_m;
2488 need_es = 1;
2491 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2492 gcc_assert (index == NULL_RTX);
2494 #if DEBUG_ALLOC
2495 fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m");
2496 debug_rtx (base);
2497 #endif
2498 if (base == NULL_RTX)
2499 return m;
2501 if (addendr && GET_CODE (addendr) == CONST_INT)
2502 addend = INTVAL (addendr);
2504 gcc_assert (REG_P (base));
2505 gcc_assert (REG_P (newbase));
2507 if (REGNO (base) == SP_REG)
2509 if (addend >= 0 && addend <= 255)
2510 return m;
2513 /* BASE should be a virtual register. We copy it to NEWBASE. If
2514 the addend is out of range for DE/HL, we use AX to compute the full
2515 address. */
2517 if (addend < 0
2518 || (addend > 255 && REGNO (newbase) != 2)
2519 || (addendr && GET_CODE (addendr) != CONST_INT))
2521 /* mov ax, vreg
2522 add ax, #imm
2523 mov hl, ax */
2524 EM (emit_insn_before (gen_movhi (AX, base), before));
2525 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2526 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2527 record_content (AX, NULL_RTX);
2528 record_content (newbase, NULL_RTX);
2530 base = newbase;
2531 addend = 0;
2533 else
2535 base = gen_and_emit_move (newbase, base, before, true);
2538 if (addend)
2540 record_content (base, NULL_RTX);
2541 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2544 #if DEBUG_ALLOC
2545 fprintf (stderr, "\033[33m");
2546 debug_rtx (m);
2547 #endif
2548 if (need_es)
2550 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2551 cfun->machine->uses_es = true;
2553 else
2554 m = change_address (m, GET_MODE (m), base);
2555 #if DEBUG_ALLOC
2556 debug_rtx (m);
2557 fprintf (stderr, "\033[0m");
2558 #endif
2559 return m;
2562 /* Copy SRC to accumulator (A or AX), placing any generated insns
2563 before BEFORE. Returns accumulator RTX. */
2564 static rtx
2565 move_to_acc (int opno, rtx before)
2567 rtx src = OP (opno);
2568 machine_mode mode = GET_MODE (src);
2570 if (REG_P (src) && REGNO (src) < 2)
2571 return src;
2573 if (mode == VOIDmode)
2574 mode = recog_data.operand_mode[opno];
2576 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2579 static void
2580 force_into_acc (rtx src, rtx before)
2582 machine_mode mode = GET_MODE (src);
2583 rtx move;
2585 if (REG_P (src) && REGNO (src) < 2)
2586 return;
2588 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2590 EM (move);
2592 emit_insn_before (move, before);
2593 record_content (AX, NULL_RTX);
2596 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2597 after AFTER. Returns accumulator RTX. */
2598 static rtx
2599 move_from_acc (unsigned int opno, rtx after)
2601 rtx dest = OP (opno);
2602 machine_mode mode = GET_MODE (dest);
2604 if (REG_P (dest) && REGNO (dest) < 2)
2605 return dest;
2607 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2610 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2611 before BEFORE. Returns reg RTX. */
2612 static rtx
2613 move_acc_to_reg (rtx acc, int regno, rtx before)
2615 machine_mode mode = GET_MODE (acc);
2616 rtx reg;
2618 reg = gen_rtx_REG (mode, regno);
2620 return gen_and_emit_move (reg, acc, before, true);
2623 /* Copy SRC to X, placing any generated insns before BEFORE.
2624 Returns X RTX. */
2625 static rtx
2626 move_to_x (int opno, rtx before)
2628 rtx src = OP (opno);
2629 machine_mode mode = GET_MODE (src);
2630 rtx reg;
2632 if (mode == VOIDmode)
2633 mode = recog_data.operand_mode[opno];
2634 reg = (mode == QImode) ? X : AX;
2636 if (mode == QImode || ! is_virtual_register (OP (opno)))
2638 OP (opno) = move_to_acc (opno, before);
2639 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
2640 return reg;
2643 return gen_and_emit_move (reg, src, before, true);
2646 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2647 Returns H/HL RTX. */
2648 static rtx
2649 move_to_hl (int opno, rtx before)
2651 rtx src = OP (opno);
2652 machine_mode mode = GET_MODE (src);
2653 rtx reg;
2655 if (mode == VOIDmode)
2656 mode = recog_data.operand_mode[opno];
2657 reg = (mode == QImode) ? L : HL;
2659 if (mode == QImode || ! is_virtual_register (OP (opno)))
2661 OP (opno) = move_to_acc (opno, before);
2662 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2663 return reg;
2666 return gen_and_emit_move (reg, src, before, true);
2669 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2670 Returns E/DE RTX. */
2671 static rtx
2672 move_to_de (int opno, rtx before)
2674 rtx src = OP (opno);
2675 machine_mode mode = GET_MODE (src);
2676 rtx reg;
2678 if (mode == VOIDmode)
2679 mode = recog_data.operand_mode[opno];
2681 reg = (mode == QImode) ? E : DE;
2683 if (mode == QImode || ! is_virtual_register (OP (opno)))
2685 OP (opno) = move_to_acc (opno, before);
2686 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2688 else
2690 gen_and_emit_move (reg, src, before, true);
2693 return reg;
2696 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2697 static void
2698 rl78_alloc_physical_registers_op1 (rtx_insn * insn)
2700 /* op[0] = func op[1] */
2702 /* We first try using A as the destination, then copying it
2703 back. */
2704 if (rtx_equal_p (OP (0), OP (1)))
2706 OP (0) =
2707 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2709 else
2711 /* If necessary, load the operands into BC and HL.
2712 Check to see if we already have OP (0) in HL
2713 and if so, swap the order. */
2714 if (MEM_P (OP (0))
2715 && already_contains (HL, XEXP (OP (0), 0)))
2717 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2718 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2720 else
2722 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2723 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2727 MAYBE_OK (insn);
2729 OP (0) = move_from_acc (0, insn);
2731 MAYBE_OK (insn);
2733 /* Try copying the src to acc first, then. This is for, for
2734 example, ZERO_EXTEND or NOT. */
2735 OP (1) = move_to_acc (1, insn);
2737 MUST_BE_OK (insn);
2740 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2741 Assumes that the current insn has already been recognised and hence the
2742 constraint data has been filled in. */
2743 static bool
2744 has_constraint (unsigned int opnum, enum constraint_num constraint)
2746 const char * p = recog_data.constraints[opnum];
2748 /* No constraints means anything is accepted. */
2749 if (p == NULL || *p == 0 || *p == ',')
2750 return true;
2754 char c;
2755 unsigned int len;
2757 c = *p;
2758 len = CONSTRAINT_LEN (c, p);
2759 gcc_assert (len > 0);
2761 switch (c)
2763 case 0:
2764 case ',':
2765 return false;
2766 default:
2767 if (lookup_constraint (p) == constraint)
2768 return true;
2770 p += len;
2772 while (1);
2775 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2776 static void
2777 rl78_alloc_physical_registers_op2 (rtx_insn * insn)
2779 rtx prev;
2780 rtx first;
2781 bool hl_used;
2782 int tmp_id;
2783 rtx saved_op1;
2785 if (rtx_equal_p (OP (0), OP (1)))
2787 OP (0) =
2788 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2789 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2791 else if (rtx_equal_p (OP (0), OP (2)))
2793 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2794 OP (0) =
2795 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2797 else
2799 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2800 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2801 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2804 MAYBE_OK (insn);
2806 prev = prev_nonnote_nondebug_insn (insn);
2807 if (recog_data.constraints[1][0] == '%'
2808 && is_virtual_register (OP (1))
2809 && ! is_virtual_register (OP (2))
2810 && ! CONSTANT_P (OP (2)))
2812 rtx tmp = OP (1);
2813 OP (1) = OP (2);
2814 OP (2) = tmp;
2817 /* Make a note of whether (H)L is being used. It matters
2818 because if OP (2) also needs reloading, then we must take
2819 care not to corrupt HL. */
2820 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2822 /* If HL is not currently being used and dest == op1 then there are
2823 some possible optimizations available by reloading one of the
2824 operands into HL, before trying to use the accumulator. */
2825 if (optimize
2826 && ! hl_used
2827 && rtx_equal_p (OP (0), OP (1)))
2829 /* If op0 is a Ws1 type memory address then switching the base
2830 address register to HL might allow us to perform an in-memory
2831 operation. (eg for the INCW instruction).
2833 FIXME: Adding the move into HL is costly if this optimization is not
2834 going to work, so for now, make sure that we know that the new insn will
2835 match the requirements of the addhi3_real pattern. Really we ought to
2836 generate a candidate sequence, test that, and then install it if the
2837 results are good. */
2838 if (satisfies_constraint_Ws1 (OP (0))
2839 && has_constraint (0, CONSTRAINT_Wh1)
2840 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2842 rtx base, index, addend, newbase;
2844 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
2845 gcc_assert (index == NULL_RTX);
2846 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2848 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2849 if (addend != NULL_RTX)
2851 newbase = gen_and_emit_move (HL, base, insn, true);
2852 record_content (newbase, NULL_RTX);
2853 newbase = gen_rtx_PLUS (HImode, newbase, addend);
2855 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
2857 /* We do not want to fail here as this means that
2858 we have inserted useless insns into the stream. */
2859 MUST_BE_OK (insn);
2862 else if (REG_P (OP (0))
2863 && satisfies_constraint_Ws1 (OP (2))
2864 && has_constraint (2, CONSTRAINT_Wh1))
2866 rtx base, index, addend, newbase;
2868 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
2869 gcc_assert (index == NULL_RTX);
2870 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2872 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2873 if (addend != NULL_RTX)
2875 gen_and_emit_move (HL, base, insn, true);
2877 if (REGNO (OP (0)) != X_REG)
2879 OP (1) = move_to_acc (1, insn);
2880 OP (0) = move_from_acc (0, insn);
2883 record_content (HL, NULL_RTX);
2884 newbase = gen_rtx_PLUS (HImode, HL, addend);
2886 OP (2) = change_address (OP (2), VOIDmode, newbase);
2888 /* We do not want to fail here as this means that
2889 we have inserted useless insns into the stream. */
2890 MUST_BE_OK (insn);
2895 OP (0) = move_from_acc (0, insn);
2897 tmp_id = get_max_insn_count ();
2898 saved_op1 = OP (1);
2900 if (rtx_equal_p (OP (1), OP (2)))
2901 OP (2) = OP (1) = move_to_acc (1, insn);
2902 else
2903 OP (1) = move_to_acc (1, insn);
2905 MAYBE_OK (insn);
2907 /* If we omitted the move of OP1 into the accumulator (because
2908 it was already there from a previous insn), then force the
2909 generation of the move instruction now. We know that we
2910 are about to emit a move into HL (or DE) via AX, and hence
2911 our optimization to remove the load of OP1 is no longer valid. */
2912 if (tmp_id == get_max_insn_count ())
2913 force_into_acc (saved_op1, insn);
2915 /* We have to copy op2 to HL (or DE), but that involves AX, which
2916 already has a live value. Emit it before those insns. */
2918 if (prev)
2919 first = next_nonnote_nondebug_insn (prev);
2920 else
2921 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2924 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2926 MUST_BE_OK (insn);
2929 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2930 static void
2931 rl78_alloc_physical_registers_ro1 (rtx_insn * insn)
2933 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2935 MAYBE_OK (insn);
2937 OP (0) = move_to_acc (0, insn);
2939 MUST_BE_OK (insn);
2942 /* Devirtualize a compare insn. */
2943 static void
2944 rl78_alloc_physical_registers_cmp (rtx_insn * insn)
2946 int tmp_id;
2947 rtx saved_op1;
2948 rtx prev = prev_nonnote_nondebug_insn (insn);
2949 rtx first;
2951 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2952 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2954 /* HI compares have to have OP (1) in AX, but QI
2955 compares do not, so it is worth checking here. */
2956 MAYBE_OK (insn);
2958 /* For an HImode compare, OP (1) must always be in AX.
2959 But if OP (1) is a REG (and not AX), then we can avoid
2960 a reload of OP (1) if we reload OP (2) into AX and invert
2961 the comparison. */
2962 if (REG_P (OP (1))
2963 && REGNO (OP (1)) != AX_REG
2964 && GET_MODE (OP (1)) == HImode
2965 && MEM_P (OP (2)))
2967 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
2969 OP (2) = move_to_acc (2, insn);
2971 switch (GET_CODE (cmp))
2973 case EQ:
2974 case NE:
2975 break;
2976 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
2977 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
2978 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
2979 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
2981 case LT:
2982 case GT:
2983 case LE:
2984 case GE:
2985 #if DEBUG_ALLOC
2986 debug_rtx (insn);
2987 #endif
2988 default:
2989 gcc_unreachable ();
2992 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
2993 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
2994 else
2995 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
2997 MUST_BE_OK (insn);
3000 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3001 should be handled by the second alternative of the cbranchhi_real pattern. */
3002 if (rtx_equal_p (OP (1), OP (2)))
3004 OP (1) = OP (2) = BC;
3005 MUST_BE_OK (insn);
3008 tmp_id = get_max_insn_count ();
3009 saved_op1 = OP (1);
3011 OP (1) = move_to_acc (1, insn);
3013 MAYBE_OK (insn);
3015 /* If we omitted the move of OP1 into the accumulator (because
3016 it was already there from a previous insn), then force the
3017 generation of the move instruction now. We know that we
3018 are about to emit a move into HL via AX, and hence our
3019 optimization to remove the load of OP1 is no longer valid. */
3020 if (tmp_id == get_max_insn_count ())
3021 force_into_acc (saved_op1, insn);
3023 /* We have to copy op2 to HL, but that involves the acc, which
3024 already has a live value. Emit it before those insns. */
3025 if (prev)
3026 first = next_nonnote_nondebug_insn (prev);
3027 else
3028 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3030 OP (2) = move_to_hl (2, first);
3032 MUST_BE_OK (insn);
3035 /* Like op2, but AX = A * X. */
3036 static void
3037 rl78_alloc_physical_registers_umul (rtx_insn * insn)
3039 rtx prev = prev_nonnote_nondebug_insn (insn);
3040 rtx first;
3041 int tmp_id;
3042 rtx saved_op1;
3044 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
3045 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
3046 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
3048 MAYBE_OK (insn);
3050 if (recog_data.constraints[1][0] == '%'
3051 && is_virtual_register (OP (1))
3052 && !is_virtual_register (OP (2))
3053 && !CONSTANT_P (OP (2)))
3055 rtx tmp = OP (1);
3056 OP (1) = OP (2);
3057 OP (2) = tmp;
3060 OP (0) = move_from_acc (0, insn);
3062 tmp_id = get_max_insn_count ();
3063 saved_op1 = OP (1);
3065 if (rtx_equal_p (OP (1), OP (2)))
3067 gcc_assert (GET_MODE (OP (2)) == QImode);
3068 /* The MULU instruction does not support duplicate arguments
3069 but we know that if we copy OP (2) to X it will do so via
3070 A and thus OP (1) will already be loaded into A. */
3071 OP (2) = move_to_x (2, insn);
3072 OP (1) = A;
3074 else
3075 OP (1) = move_to_acc (1, insn);
3077 MAYBE_OK (insn);
3079 /* If we omitted the move of OP1 into the accumulator (because
3080 it was already there from a previous insn), then force the
3081 generation of the move instruction now. We know that we
3082 are about to emit a move into HL (or DE) via AX, and hence
3083 our optimization to remove the load of OP1 is no longer valid. */
3084 if (tmp_id == get_max_insn_count ())
3085 force_into_acc (saved_op1, insn);
3087 /* We have to copy op2 to X, but that involves the acc, which
3088 already has a live value. Emit it before those insns. */
3090 if (prev)
3091 first = next_nonnote_nondebug_insn (prev);
3092 else
3093 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3095 OP (2) = move_to_x (2, first);
3097 MUST_BE_OK (insn);
3100 static void
3101 rl78_alloc_address_registers_macax (rtx_insn * insn)
3103 int which, op;
3104 bool replace_in_op0 = false;
3105 bool replace_in_op1 = false;
3107 MAYBE_OK (insn);
3109 /* Two different MEMs are not allowed. */
3110 which = 0;
3111 for (op = 2; op >= 0; op --)
3113 if (MEM_P (OP (op)))
3115 if (op == 0 && replace_in_op0)
3116 continue;
3117 if (op == 1 && replace_in_op1)
3118 continue;
3120 switch (which)
3122 case 0:
3123 /* If we replace a MEM, make sure that we replace it for all
3124 occurrences of the same MEM in the insn. */
3125 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3126 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3128 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3129 if (op == 2
3130 && MEM_P (OP (op))
3131 && ((GET_CODE (XEXP (OP (op), 0)) == REG
3132 && REGNO (XEXP (OP (op), 0)) == SP_REG)
3133 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3134 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3136 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3137 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3139 if (replace_in_op0)
3140 OP (0) = OP (op);
3141 if (replace_in_op1)
3142 OP (1) = OP (op);
3143 break;
3144 case 1:
3145 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3146 break;
3147 case 2:
3148 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3149 break;
3151 which ++;
3155 MUST_BE_OK (insn);
3158 /* Scan all insns and devirtualize them. */
3159 static void
3160 rl78_alloc_physical_registers (void)
3162 /* During most of the compile, gcc is dealing with virtual
3163 registers. At this point, we need to assign physical registers
3164 to the vitual ones, and copy in/out as needed. */
3166 rtx_insn *insn, *curr;
3167 enum attr_valloc valloc_method;
3169 for (insn = get_insns (); insn; insn = curr)
3171 int i;
3173 curr = next_nonnote_nondebug_insn (insn);
3175 if (INSN_P (insn)
3176 && (GET_CODE (PATTERN (insn)) == SET
3177 || GET_CODE (PATTERN (insn)) == CALL)
3178 && INSN_CODE (insn) == -1)
3180 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3181 continue;
3182 i = recog (PATTERN (insn), insn, 0);
3183 if (i == -1)
3185 debug_rtx (insn);
3186 gcc_unreachable ();
3188 INSN_CODE (insn) = i;
3192 cfun->machine->virt_insns_ok = 0;
3193 cfun->machine->real_insns_ok = 1;
3195 clear_content_memory ();
3197 for (insn = get_insns (); insn; insn = curr)
3199 rtx pattern;
3201 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3203 if (!INSN_P (insn))
3205 if (LABEL_P (insn))
3206 clear_content_memory ();
3208 continue;
3211 if (dump_file)
3212 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3214 pattern = PATTERN (insn);
3215 if (GET_CODE (pattern) == PARALLEL)
3216 pattern = XVECEXP (pattern, 0, 0);
3217 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3218 clear_content_memory ();
3219 if (GET_CODE (pattern) != SET
3220 && GET_CODE (pattern) != CALL)
3221 continue;
3222 if (GET_CODE (pattern) == SET
3223 && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3224 continue;
3226 valloc_method = get_attr_valloc (insn);
3228 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3230 if (valloc_method == VALLOC_MACAX)
3232 record_content (AX, NULL_RTX);
3233 record_content (BC, NULL_RTX);
3234 record_content (DE, NULL_RTX);
3237 if (insn_ok_now (insn))
3238 continue;
3240 INSN_CODE (insn) = -1;
3242 if (RTX_FRAME_RELATED_P (insn))
3243 virt_insn_was_frame = 1;
3244 else
3245 virt_insn_was_frame = 0;
3247 switch (valloc_method)
3249 case VALLOC_OP1:
3250 rl78_alloc_physical_registers_op1 (insn);
3251 break;
3252 case VALLOC_OP2:
3253 rl78_alloc_physical_registers_op2 (insn);
3254 break;
3255 case VALLOC_RO1:
3256 rl78_alloc_physical_registers_ro1 (insn);
3257 break;
3258 case VALLOC_CMP:
3259 rl78_alloc_physical_registers_cmp (insn);
3260 break;
3261 case VALLOC_UMUL:
3262 rl78_alloc_physical_registers_umul (insn);
3263 break;
3264 case VALLOC_MACAX:
3265 /* Macro that clobbers AX. */
3266 rl78_alloc_address_registers_macax (insn);
3267 record_content (AX, NULL_RTX);
3268 record_content (BC, NULL_RTX);
3269 record_content (DE, NULL_RTX);
3270 break;
3273 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3274 clear_content_memory ();
3275 else
3276 process_postponed_content_update ();
3279 #if DEBUG_ALLOC
3280 fprintf (stderr, "\033[0m");
3281 #endif
3284 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3285 This function scans for uses of registers; the last use (i.e. first
3286 encounter when scanning backwards) triggers a REG_DEAD note if the
3287 reg was previously in DEAD[]. */
3288 static void
3289 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3291 const char *fmt;
3292 int i, r;
3293 enum rtx_code code;
3295 if (!s)
3296 return;
3298 code = GET_CODE (s);
3300 switch (code)
3302 /* Compare registers by number. */
3303 case REG:
3304 r = REGNO (s);
3305 if (dump_file)
3307 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3308 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3309 print_rtl_single (dump_file, s);
3311 if (dead [r])
3312 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3313 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3314 dead [r + i] = 0;
3315 return;
3317 /* These codes have no constituent expressions
3318 and are unique. */
3319 case SCRATCH:
3320 case CC0:
3321 case PC:
3322 return;
3324 case CONST_INT:
3325 case CONST_VECTOR:
3326 case CONST_DOUBLE:
3327 case CONST_FIXED:
3328 /* These are kept unique for a given value. */
3329 return;
3331 default:
3332 break;
3335 fmt = GET_RTX_FORMAT (code);
3337 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3339 if (fmt[i] == 'E')
3341 int j;
3342 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3343 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3345 else if (fmt[i] == 'e')
3346 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3350 /* Like the previous function, but scan for SETs instead. */
3351 static void
3352 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3354 int r, i;
3356 if (GET_CODE (d) != REG)
3357 return;
3359 r = REGNO (d);
3360 if (dead [r])
3361 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3362 if (dump_file)
3363 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3364 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3365 dead [r + i] = 1;
3368 /* This is a rather crude register death pass. Death status is reset
3369 at every jump or call insn. */
3370 static void
3371 rl78_calculate_death_notes (void)
3373 char dead[FIRST_PSEUDO_REGISTER];
3374 rtx insn, p, s, d;
3375 int i;
3377 memset (dead, 0, sizeof (dead));
3379 for (insn = get_last_insn ();
3380 insn;
3381 insn = prev_nonnote_nondebug_insn (insn))
3383 if (dump_file)
3385 fprintf (dump_file, "\n--------------------------------------------------");
3386 fprintf (dump_file, "\nDead:");
3387 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3388 if (dead[i])
3389 fprintf (dump_file, " %s", reg_names[i]);
3390 fprintf (dump_file, "\n");
3391 print_rtl_single (dump_file, insn);
3394 switch (GET_CODE (insn))
3396 case INSN:
3397 p = PATTERN (insn);
3398 switch (GET_CODE (p))
3400 case SET:
3401 s = SET_SRC (p);
3402 d = SET_DEST (p);
3403 rl78_note_reg_set (dead, d, insn);
3404 rl78_note_reg_uses (dead, s, insn);
3405 break;
3407 case USE:
3408 rl78_note_reg_uses (dead, p, insn);
3409 break;
3411 default:
3412 break;
3414 break;
3416 case JUMP_INSN:
3417 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3419 memset (dead, 1, sizeof (dead));
3420 /* We expect a USE just prior to this, which will mark
3421 the actual return registers. The USE will have a
3422 death note, but we aren't going to be modifying it
3423 after this pass. */
3424 break;
3426 case CALL_INSN:
3427 memset (dead, 0, sizeof (dead));
3428 break;
3430 default:
3431 break;
3433 if (dump_file)
3434 print_rtl_single (dump_file, insn);
3438 /* Helper function to reset the origins in RP and the age in AGE for
3439 all registers. */
3440 static void
3441 reset_origins (int *rp, int *age)
3443 int i;
3444 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3446 rp[i] = i;
3447 age[i] = 0;
3451 /* The idea behind this optimization is to look for cases where we
3452 move data from A to B to C, and instead move from A to B, and A to
3453 C. If B is a virtual register or memory, this is a big win on its
3454 own. If B turns out to be unneeded after this, it's a bigger win.
3455 For each register, we try to determine where it's value originally
3456 came from, if it's propogated purely through moves (and not
3457 computes). The ORIGINS[] array has the regno for the "origin" of
3458 the value in the [regno] it's indexed by. */
3459 static void
3460 rl78_propogate_register_origins (void)
3462 int origins[FIRST_PSEUDO_REGISTER];
3463 int age[FIRST_PSEUDO_REGISTER];
3464 int i;
3465 rtx_insn *insn, *ninsn = NULL;
3466 rtx pat;
3468 reset_origins (origins, age);
3470 for (insn = get_insns (); insn; insn = ninsn)
3472 ninsn = next_nonnote_nondebug_insn (insn);
3474 if (dump_file)
3476 fprintf (dump_file, "\n");
3477 fprintf (dump_file, "Origins:");
3478 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3479 if (origins[i] != i)
3480 fprintf (dump_file, " r%d=r%d", i, origins[i]);
3481 fprintf (dump_file, "\n");
3482 print_rtl_single (dump_file, insn);
3485 switch (GET_CODE (insn))
3487 case CODE_LABEL:
3488 case BARRIER:
3489 case CALL_INSN:
3490 case JUMP_INSN:
3491 reset_origins (origins, age);
3492 break;
3494 default:
3495 break;
3497 case INSN:
3498 pat = PATTERN (insn);
3500 if (GET_CODE (pat) == PARALLEL)
3502 rtx clobber = XVECEXP (pat, 0, 1);
3503 pat = XVECEXP (pat, 0, 0);
3504 if (GET_CODE (clobber) == CLOBBER
3505 && GET_CODE (XEXP (clobber, 0)) == REG)
3507 int cr = REGNO (XEXP (clobber, 0));
3508 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3509 if (dump_file)
3510 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3511 for (i = 0; i < mb; i++)
3513 origins[cr + i] = cr + i;
3514 age[cr + i] = 0;
3517 else
3518 break;
3521 if (GET_CODE (pat) == SET)
3523 rtx src = SET_SRC (pat);
3524 rtx dest = SET_DEST (pat);
3525 int mb = GET_MODE_SIZE (GET_MODE (dest));
3527 if (GET_CODE (dest) == REG)
3529 int dr = REGNO (dest);
3531 if (GET_CODE (src) == REG)
3533 int sr = REGNO (src);
3534 int same = 1;
3535 int best_age, best_reg;
3537 /* See if the copy is not needed. */
3538 for (i = 0; i < mb; i ++)
3539 if (origins[dr + i] != origins[sr + i])
3540 same = 0;
3541 if (same)
3543 if (dump_file)
3544 fprintf (dump_file, "deleting because dest already has correct value\n");
3545 delete_insn (insn);
3546 break;
3549 if (dr < 8 || sr >= 8)
3551 int ar;
3553 best_age = -1;
3554 best_reg = -1;
3555 /* See if the copy can be made from another
3556 bank 0 register instead, instead of the
3557 virtual src register. */
3558 for (ar = 0; ar < 8; ar += mb)
3560 same = 1;
3561 for (i = 0; i < mb; i ++)
3562 if (origins[ar + i] != origins[sr + i])
3563 same = 0;
3565 /* The chip has some reg-reg move limitations. */
3566 if (mb == 1 && dr > 3)
3567 same = 0;
3569 if (same)
3571 if (best_age == -1 || best_age > age[sr + i])
3573 best_age = age[sr + i];
3574 best_reg = sr;
3579 if (best_reg != -1)
3581 /* FIXME: copy debug info too. */
3582 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3583 sr = best_reg;
3587 for (i = 0; i < mb; i++)
3589 origins[dr + i] = origins[sr + i];
3590 age[dr + i] = age[sr + i] + 1;
3593 else
3595 /* The destination is computed, its origin is itself. */
3596 if (dump_file)
3597 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3598 dr, mb, mb == 1 ? "" : "s");
3599 for (i = 0; i < mb; i ++)
3601 origins[dr + i] = dr + i;
3602 age[dr + i] = 0;
3606 /* Any registers marked with that reg as an origin are reset. */
3607 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3608 if (origins[i] >= dr && origins[i] < dr + mb)
3610 origins[i] = i;
3611 age[i] = 0;
3615 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3616 if (get_attr_valloc (insn) == VALLOC_MACAX)
3618 if (dump_file)
3619 fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
3620 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3621 if (i <= 3 || origins[i] <= 3)
3623 origins[i] = i;
3624 age[i] = 0;
3628 if (GET_CODE (src) == ASHIFT
3629 || GET_CODE (src) == ASHIFTRT
3630 || GET_CODE (src) == LSHIFTRT)
3632 rtx count = XEXP (src, 1);
3633 if (GET_CODE (count) == REG)
3635 /* Special case - our pattern clobbers the count register. */
3636 int r = REGNO (count);
3637 if (dump_file)
3638 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3639 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3640 if (i == r || origins[i] == r)
3642 origins[i] = i;
3643 age[i] = 0;
3648 else if (GET_CODE (pat) == CLOBBER
3649 && GET_CODE (XEXP (pat, 0)) == REG)
3651 if (REG_P (XEXP (pat, 0)))
3653 unsigned int reg = REGNO (XEXP (pat, 0));
3655 origins[reg] = reg;
3656 age[reg] = 0;
3663 /* Remove any SETs where the destination is unneeded. */
3664 static void
3665 rl78_remove_unused_sets (void)
3667 rtx_insn *insn, *ninsn = NULL;
3668 rtx dest;
3670 for (insn = get_insns (); insn; insn = ninsn)
3672 ninsn = next_nonnote_nondebug_insn (insn);
3674 rtx set = single_set (insn);
3675 if (set == NULL)
3676 continue;
3678 dest = SET_DEST (set);
3680 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3681 continue;
3683 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3684 delete_insn (insn);
3688 /* This is the top of the devritualization pass. */
3689 static void
3690 rl78_reorg (void)
3692 /* split2 only happens when optimizing, but we need all movSIs to be
3693 split now. */
3694 if (optimize <= 0)
3695 split_all_insns ();
3697 rl78_alloc_physical_registers ();
3699 if (dump_file)
3701 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3702 print_rtl_with_bb (dump_file, get_insns (), 0);
3705 rl78_propogate_register_origins ();
3706 rl78_calculate_death_notes ();
3708 if (dump_file)
3710 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3711 print_rtl_with_bb (dump_file, get_insns (), 0);
3712 fprintf (dump_file, "\n======================================================================\n");
3715 rl78_remove_unused_sets ();
3717 /* The code after devirtualizing has changed so much that at this point
3718 we might as well just rescan everything. Note that
3719 df_rescan_all_insns is not going to help here because it does not
3720 touch the artificial uses and defs. */
3721 df_finish_pass (true);
3722 if (optimize > 1)
3723 df_live_add_problem ();
3724 df_scan_alloc (NULL);
3725 df_scan_blocks ();
3727 if (optimize)
3728 df_analyze ();
3731 #undef TARGET_RETURN_IN_MEMORY
3732 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3734 static bool
3735 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3737 const HOST_WIDE_INT size = int_size_in_bytes (type);
3738 return (size == -1 || size > 8);
3742 #undef TARGET_RTX_COSTS
3743 #define TARGET_RTX_COSTS rl78_rtx_costs
3745 static bool rl78_rtx_costs (rtx x,
3746 int code,
3747 int outer_code ATTRIBUTE_UNUSED,
3748 int opno ATTRIBUTE_UNUSED,
3749 int * total,
3750 bool speed ATTRIBUTE_UNUSED)
3752 if (code == IF_THEN_ELSE)
3753 return COSTS_N_INSNS (10);
3754 if (GET_MODE (x) == SImode)
3756 switch (code)
3758 case MULT:
3759 if (RL78_MUL_RL78)
3760 *total = COSTS_N_INSNS (14);
3761 else if (RL78_MUL_G13)
3762 *total = COSTS_N_INSNS (29);
3763 else
3764 *total = COSTS_N_INSNS (500);
3765 return true;
3766 case PLUS:
3767 *total = COSTS_N_INSNS (8);
3768 return true;
3769 case ASHIFT:
3770 case ASHIFTRT:
3771 case LSHIFTRT:
3772 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3774 switch (INTVAL (XEXP (x, 1)))
3776 case 0: *total = COSTS_N_INSNS (0); break;
3777 case 1: *total = COSTS_N_INSNS (6); break;
3778 case 2: case 3: case 4: case 5: case 6: case 7:
3779 *total = COSTS_N_INSNS (10); break;
3780 case 8: *total = COSTS_N_INSNS (6); break;
3781 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3782 *total = COSTS_N_INSNS (10); break;
3783 case 16: *total = COSTS_N_INSNS (3); break;
3784 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3785 *total = COSTS_N_INSNS (4); break;
3786 case 24: *total = COSTS_N_INSNS (4); break;
3787 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3788 *total = COSTS_N_INSNS (5); break;
3791 else
3792 *total = COSTS_N_INSNS (10+4*16);
3793 return true;
3796 return false;
3800 #undef TARGET_UNWIND_WORD_MODE
3801 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3803 static machine_mode
3804 rl78_unwind_word_mode (void)
3806 return HImode;
3810 struct gcc_target targetm = TARGET_INITIALIZER;
3812 #include "gt-rl78.h"