* config/rl78/rl78.c (need_to_save): Change return type to bool.
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob70e1dee2f1456af7508c8ef2fd282a7270ffd880
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2013 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 "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "output.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "function.h"
35 #include "expr.h"
36 #include "optabs.h"
37 #include "libfuncs.h"
38 #include "recog.h"
39 #include "diagnostic-core.h"
40 #include "toplev.h"
41 #include "reload.h"
42 #include "df.h"
43 #include "ggc.h"
44 #include "tm_p.h"
45 #include "debug.h"
46 #include "target.h"
47 #include "target-def.h"
48 #include "langhooks.h"
49 #include "rl78-protos.h"
50 #include "dumpfile.h"
51 #include "tree-pass.h"
52 #include "context.h"
53 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
54 #include "insn-flags.h" /* for gen_*(). */
56 static inline bool is_interrupt_func (const_tree decl);
57 static inline bool is_brk_interrupt_func (const_tree decl);
58 static void rl78_reorg (void);
61 /* Debugging statements are tagged with DEBUG0 only so that they can
62 be easily enabled individually, by replacing the '0' with '1' as
63 needed. */
64 #define DEBUG0 0
65 #define DEBUG1 1
67 /* REGISTER_NAMES has the names for individual 8-bit registers, but
68 these have the names we need to use when referring to 16-bit
69 register pairs. */
70 static const char * const word_regnames[] =
72 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
74 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
75 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
76 "sp", "ap", "psw", "es", "cs"
79 struct GTY(()) machine_function
81 /* If set, the rest of the fields have been computed. */
82 int computed;
83 /* Which register pairs need to be pushed in the prologue. */
84 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
86 /* These fields describe the frame layout... */
87 /* arg pointer */
88 /* 4 bytes for saved PC */
89 int framesize_regs;
90 /* frame pointer */
91 int framesize_locals;
92 int framesize_outgoing;
93 /* stack pointer */
94 int framesize;
96 /* If set, recog is allowed to match against the "real" patterns. */
97 int real_insns_ok;
98 /* If set, recog is allowed to match against the "virtual" patterns. */
99 int virt_insns_ok;
100 /* Set if the current function needs to clean up any trampolines. */
101 int trampolines_used;
104 /* This is our init_machine_status, as set in
105 rl78_option_override. */
106 static struct machine_function *
107 rl78_init_machine_status (void)
109 struct machine_function *m;
111 m = ggc_alloc_cleared_machine_function ();
112 m->virt_insns_ok = 1;
114 return m;
117 /* Returns whether to run the devirtualization pass. */
118 static bool
119 devirt_gate (void)
121 return true;
124 /* Runs the devirtualization pass. */
125 static unsigned int
126 devirt_pass (void)
128 rl78_reorg ();
129 return 0;
132 /* This pass converts virtual instructions using virtual registers, to
133 real instructions using real registers. Rather than run it as
134 reorg, we reschedule it before vartrack to help with debugging. */
135 namespace {
137 const pass_data pass_data_rl78_devirt =
139 RTL_PASS, /* type */
140 "devirt", /* name */
141 OPTGROUP_NONE, /* optinfo_flags */
142 true, /* has_gate */
143 true, /* has_execute */
144 TV_MACH_DEP, /* tv_id */
145 0, /* properties_required */
146 0, /* properties_provided */
147 0, /* properties_destroyed */
148 0, /* todo_flags_start */
149 0, /* todo_flags_finish */
152 class pass_rl78_devirt : public rtl_opt_pass
154 public:
155 pass_rl78_devirt(gcc::context *ctxt)
156 : rtl_opt_pass(pass_data_rl78_devirt, ctxt)
160 /* opt_pass methods: */
161 bool gate () { return devirt_gate (); }
162 unsigned int execute () { return devirt_pass (); }
165 } // anon namespace
167 rtl_opt_pass *
168 make_pass_rl78_devirt (gcc::context *ctxt)
170 return new pass_rl78_devirt (ctxt);
173 static unsigned int
174 move_elim_pass (void)
176 rtx insn, ninsn, prev = NULL_RTX;
178 for (insn = get_insns (); insn; insn = ninsn)
180 rtx set;
182 ninsn = next_nonnote_nondebug_insn (insn);
184 if ((set = single_set (insn)) == NULL_RTX)
186 prev = NULL_RTX;
187 continue;
190 /* If we have two SET insns in a row (without anything
191 between them) and the source of the second one is the
192 destination of the first one, and vice versa, then we
193 can eliminate the second SET. */
194 if (prev
195 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
196 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
199 if (dump_file)
200 fprintf (dump_file, " Delete insn %d because it is redundant\n",
201 INSN_UID (insn));
203 delete_insn (insn);
204 prev = NULL_RTX;
206 else
207 prev = set;
210 if (dump_file)
211 print_rtl_with_bb (dump_file, get_insns (), 0);
213 return 0;
216 namespace {
218 const pass_data pass_data_rl78_move_elim =
220 RTL_PASS, /* type */
221 "move_elim", /* name */
222 OPTGROUP_NONE, /* optinfo_flags */
223 true, /* has_gate */
224 true, /* has_execute */
225 TV_MACH_DEP, /* tv_id */
226 0, /* properties_required */
227 0, /* properties_provided */
228 0, /* properties_destroyed */
229 0, /* todo_flags_start */
230 0, /* todo_flags_finish */
233 class pass_rl78_move_elim : public rtl_opt_pass
235 public:
236 pass_rl78_move_elim(gcc::context *ctxt)
237 : rtl_opt_pass(pass_data_rl78_move_elim, ctxt)
241 /* opt_pass methods: */
242 bool gate () { return devirt_gate (); }
243 unsigned int execute () { return move_elim_pass (); }
246 } // anon namespace
248 rtl_opt_pass *
249 make_pass_rl78_move_elim (gcc::context *ctxt)
251 return new pass_rl78_move_elim (ctxt);
254 #undef TARGET_ASM_FILE_START
255 #define TARGET_ASM_FILE_START rl78_asm_file_start
257 static void
258 rl78_asm_file_start (void)
260 int i;
262 if (TARGET_G10)
264 /* The memory used is 0xffec8 to 0xffedf; real registers are in
265 0xffee0 to 0xffee7. */
266 for (i = 8; i < 32; i++)
267 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
269 else
271 for (i = 0; i < 8; i++)
273 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
274 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
278 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
279 static struct register_pass_info rl78_devirt_info =
281 rl78_devirt_pass,
282 "pro_and_epilogue",
284 PASS_POS_INSERT_BEFORE
287 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
288 static struct register_pass_info rl78_move_elim_info =
290 rl78_move_elim_pass,
291 "bbro",
293 PASS_POS_INSERT_AFTER
296 register_pass (& rl78_devirt_info);
297 register_pass (& rl78_move_elim_info);
301 #undef TARGET_OPTION_OVERRIDE
302 #define TARGET_OPTION_OVERRIDE rl78_option_override
304 static void
305 rl78_option_override (void)
307 flag_omit_frame_pointer = 1;
308 flag_no_function_cse = 1;
309 flag_split_wide_types = 0;
311 init_machine_status = rl78_init_machine_status;
314 /* Most registers are 8 bits. Some are 16 bits because, for example,
315 gcc doesn't like dealing with $FP as a register pair. This table
316 maps register numbers to size in bytes. */
317 static const int register_sizes[] =
319 1, 1, 1, 1, 1, 1, 1, 1,
320 1, 1, 1, 1, 1, 1, 1, 1,
321 1, 1, 1, 1, 1, 1, 2, 1,
322 1, 1, 1, 1, 1, 1, 1, 1,
323 2, 2, 1, 1, 1
326 /* Predicates used in the MD patterns. This one is true when virtual
327 insns may be matched, which typically means before (or during) the
328 devirt pass. */
329 bool
330 rl78_virt_insns_ok (void)
332 if (cfun)
333 return cfun->machine->virt_insns_ok;
334 return true;
337 /* Predicates used in the MD patterns. This one is true when real
338 insns may be matched, which typically means after (or during) the
339 devirt pass. */
340 bool
341 rl78_real_insns_ok (void)
343 if (cfun)
344 return cfun->machine->real_insns_ok;
345 return false;
348 /* Implements HARD_REGNO_NREGS. */
350 rl78_hard_regno_nregs (int regno, enum machine_mode mode)
352 int rs = register_sizes[regno];
353 if (rs < 1)
354 rs = 1;
355 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
358 /* Implements HARD_REGNO_MODE_OK. */
360 rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
362 int s = GET_MODE_SIZE (mode);
364 if (s < 1)
365 return 0;
366 /* These are not to be used by gcc. */
367 if (regno == 23 || regno == ES_REG || regno == CS_REG)
368 return 0;
369 /* $fp can alway sbe accessed as a 16-bit value. */
370 if (regno == FP_REG && s == 2)
371 return 1;
372 if (regno < SP_REG)
374 /* Since a reg-reg move is really a reg-mem move, we must
375 enforce alignment. */
376 if (s > 1 && (regno % 2))
377 return 0;
378 return 1;
380 if (s == CC_REGNUM)
381 return (mode == BImode);
382 /* All other registers must be accessed in their natural sizes. */
383 if (s == register_sizes [regno])
384 return 1;
385 return 0;
388 /* Simplify_gen_subreg() doesn't handle memory references the way we
389 need it to below, so we use this function for when we must get a
390 valid subreg in a "natural" state. */
391 static rtx
392 rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
394 if (GET_CODE (r) == MEM)
395 return adjust_address (r, mode, byte);
396 else
397 return simplify_gen_subreg (mode, r, omode, byte);
400 /* Used by movsi. Split SImode moves into two HImode moves, using
401 appropriate patterns for the upper and lower halves of symbols. */
402 void
403 rl78_expand_movsi (rtx *operands)
405 rtx op00, op02, op10, op12;
407 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
408 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
409 if (GET_CODE (operands[1]) == CONST
410 || GET_CODE (operands[1]) == SYMBOL_REF)
412 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
413 op10 = gen_rtx_CONST (HImode, op10);
414 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
415 op12 = gen_rtx_CONST (HImode, op12);
417 else
419 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
420 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
423 if (rtx_equal_p (operands[0], operands[1]))
425 else if (rtx_equal_p (op00, op12))
427 emit_move_insn (op02, op12);
428 emit_move_insn (op00, op10);
430 else
432 emit_move_insn (op00, op10);
433 emit_move_insn (op02, op12);
437 void
438 rl78_split_movsi (rtx *operands)
440 rtx op00, op02, op10, op12;
442 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
443 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
444 if (GET_CODE (operands[1]) == CONST
445 || GET_CODE (operands[1]) == SYMBOL_REF)
447 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
448 op10 = gen_rtx_CONST (HImode, op10);
449 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
450 op12 = gen_rtx_CONST (HImode, op12);
452 else
454 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
455 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
458 if (rtx_equal_p (operands[0], operands[1]))
460 else if (rtx_equal_p (op00, op12))
462 operands[2] = op02;
463 operands[4] = op12;
464 operands[3] = op00;
465 operands[5] = op10;
467 else
469 operands[2] = op00;
470 operands[4] = op10;
471 operands[3] = op02;
472 operands[5] = op12;
477 /* Used by various two-operand expanders which cannot accept all
478 operands in the "far" namespace. Force some such operands into
479 registers so that each pattern has at most one far operand. */
481 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
483 int did = 0;
484 rtx temp_reg = NULL;
486 /* FIXME: in the future, be smarter about only doing this if the
487 other operand is also far, assuming the devirtualizer can also
488 handle that. */
489 if (rl78_far_p (operands[0]))
491 temp_reg = operands[0];
492 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
493 did = 1;
495 if (!did)
496 return 0;
498 emit_insn (gen (operands[0], operands[1]));
499 if (temp_reg)
500 emit_move_insn (temp_reg, operands[0]);
501 return 1;
504 /* Likewise, but for three-operand expanders. */
506 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
508 int did = 0;
509 rtx temp_reg = NULL;
511 /* FIXME: Likewise. */
512 if (rl78_far_p (operands[1]))
514 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
515 emit_move_insn (temp_reg, operands[1]);
516 operands[1] = temp_reg;
517 did = 1;
519 if (rl78_far_p (operands[0]))
521 temp_reg = operands[0];
522 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
523 did = 1;
525 if (!did)
526 return 0;
528 emit_insn (gen (operands[0], operands[1], operands[2]));
529 if (temp_reg)
530 emit_move_insn (temp_reg, operands[0]);
531 return 1;
534 #undef TARGET_CAN_ELIMINATE
535 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
537 static bool
538 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
540 return true;
543 /* Returns true if the given register needs to be saved by the
544 current function. */
545 static bool
546 need_to_save (unsigned int regno)
548 if (is_interrupt_func (cfun->decl))
550 /* We don't need to save registers that have
551 been reserved for interrupt handlers. */
552 if (regno > 23)
553 return false;
555 /* If the handler is a non-leaf function then it may call
556 non-interrupt aware routines which will happily clobber
557 any call_used registers, so we have to preserve them. */
558 if (!crtl->is_leaf && call_used_regs[regno])
559 return true;
561 /* Otherwise we only have to save a register, call_used
562 or not, if it is used by this handler. */
563 return df_regs_ever_live_p (regno);
566 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
567 return true;
568 if (fixed_regs[regno])
569 return false;
570 if (crtl->calls_eh_return)
571 return true;
572 if (df_regs_ever_live_p (regno)
573 && !call_used_regs[regno])
574 return true;
575 return false;
578 /* We use this to wrap all emitted insns in the prologue. */
579 static rtx
580 F (rtx x)
582 RTX_FRAME_RELATED_P (x) = 1;
583 return x;
586 /* Compute all the frame-related fields in our machine_function
587 structure. */
588 static void
589 rl78_compute_frame_info (void)
591 int i;
593 cfun->machine->computed = 1;
594 cfun->machine->framesize_regs = 0;
595 cfun->machine->framesize_locals = get_frame_size ();
596 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
598 for (i = 0; i < 16; i ++)
599 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
601 cfun->machine->need_to_push [i] = 1;
602 cfun->machine->framesize_regs += 2;
604 else
605 cfun->machine->need_to_push [i] = 0;
607 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
608 cfun->machine->framesize_locals ++;
610 cfun->machine->framesize = (cfun->machine->framesize_regs
611 + cfun->machine->framesize_locals
612 + cfun->machine->framesize_outgoing);
615 /* Returns true if the provided function has the specified attribute. */
616 static inline bool
617 has_func_attr (const_tree decl, const char * func_attr)
619 if (decl == NULL_TREE)
620 decl = current_function_decl;
622 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
625 /* Returns true if the provided function has the "interrupt" attribute. */
626 static inline bool
627 is_interrupt_func (const_tree decl)
629 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
632 /* Returns true if the provided function has the "brk_interrupt" attribute. */
633 static inline bool
634 is_brk_interrupt_func (const_tree decl)
636 return has_func_attr (decl, "brk_interrupt");
639 /* Check "interrupt" attributes. */
640 static tree
641 rl78_handle_func_attribute (tree * node,
642 tree name,
643 tree args,
644 int flags ATTRIBUTE_UNUSED,
645 bool * no_add_attrs)
647 gcc_assert (DECL_P (* node));
648 gcc_assert (args == NULL_TREE);
650 if (TREE_CODE (* node) != FUNCTION_DECL)
652 warning (OPT_Wattributes, "%qE attribute only applies to functions",
653 name);
654 * no_add_attrs = true;
657 /* FIXME: We ought to check that the interrupt and exception
658 handler attributes have been applied to void functions. */
659 return NULL_TREE;
662 #undef TARGET_ATTRIBUTE_TABLE
663 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
665 /* Table of RL78-specific attributes. */
666 const struct attribute_spec rl78_attribute_table[] =
668 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
669 affects_type_identity. */
670 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
671 false },
672 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
673 false },
674 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute,
675 false },
676 { NULL, 0, 0, false, false, false, NULL, false }
681 /* Break down an address RTX into its component base/index/addend
682 portions and return TRUE if the address is of a valid form, else
683 FALSE. */
684 static bool
685 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
687 *base = NULL_RTX;
688 *index = NULL_RTX;
689 *addend = NULL_RTX;
691 if (GET_CODE (x) == REG)
693 *base = x;
694 return true;
697 /* We sometimes get these without the CONST wrapper */
698 if (GET_CODE (x) == PLUS
699 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
700 && GET_CODE (XEXP (x, 1)) == CONST_INT)
702 *addend = x;
703 return true;
706 if (GET_CODE (x) == PLUS)
708 *base = XEXP (x, 0);
709 x = XEXP (x, 1);
711 if (GET_CODE (*base) != REG
712 && GET_CODE (x) == REG)
714 rtx tmp = *base;
715 *base = x;
716 x = tmp;
719 if (GET_CODE (*base) != REG)
720 return false;
722 if (GET_CODE (x) == ZERO_EXTEND
723 && GET_CODE (XEXP (x, 0)) == REG)
725 *index = XEXP (x, 0);
726 return false;
730 switch (GET_CODE (x))
732 case PLUS:
733 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
734 && GET_CODE (XEXP (x, 0)) == CONST_INT)
736 *addend = x;
737 return true;
739 /* fall through */
740 case MEM:
741 case REG:
742 return false;
744 case CONST:
745 case SYMBOL_REF:
746 case CONST_INT:
747 *addend = x;
748 return true;
750 default:
751 return false;
754 return false;
757 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
758 addressing. */
759 bool
760 rl78_hl_b_c_addr_p (rtx op)
762 rtx hl, bc;
764 if (GET_CODE (op) != PLUS)
765 return false;
766 hl = XEXP (op, 0);
767 bc = XEXP (op, 1);
768 if (GET_CODE (hl) == ZERO_EXTEND)
770 rtx tmp = hl;
771 hl = bc;
772 bc = tmp;
774 if (GET_CODE (hl) != REG)
775 return false;
776 if (GET_CODE (bc) != ZERO_EXTEND)
777 return false;
778 bc = XEXP (bc, 0);
779 if (GET_CODE (bc) != REG)
780 return false;
781 if (REGNO (hl) != HL_REG)
782 return false;
783 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
784 return false;
786 return true;
789 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
791 /* Used in various constraints and predicates to match operands in the
792 "far" address space. */
794 rl78_far_p (rtx x)
796 if (! MEM_P (x))
797 return 0;
798 #if DEBUG0
799 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
800 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
801 #endif
802 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
805 /* Return the appropriate mode for a named address pointer. */
806 #undef TARGET_ADDR_SPACE_POINTER_MODE
807 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
808 static enum machine_mode
809 rl78_addr_space_pointer_mode (addr_space_t addrspace)
811 switch (addrspace)
813 case ADDR_SPACE_GENERIC:
814 return HImode;
815 case ADDR_SPACE_FAR:
816 return SImode;
817 default:
818 gcc_unreachable ();
822 /* Returns TRUE for valid addresses. */
823 #undef TARGET_VALID_POINTER_MODE
824 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
825 static bool
826 rl78_valid_pointer_mode (enum machine_mode m)
828 return (m == HImode || m == SImode);
831 /* Return the appropriate mode for a named address address. */
832 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
833 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
834 static enum machine_mode
835 rl78_addr_space_address_mode (addr_space_t addrspace)
837 switch (addrspace)
839 case ADDR_SPACE_GENERIC:
840 return HImode;
841 case ADDR_SPACE_FAR:
842 return SImode;
843 default:
844 gcc_unreachable ();
848 #undef TARGET_LEGITIMATE_CONSTANT_P
849 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
851 static bool
852 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
854 return true;
857 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
858 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
860 bool
861 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
862 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
864 rtx base, index, addend;
866 if (GET_CODE (x) == UNSPEC
867 && XINT (x, 1) == UNS_ES_ADDR)
868 x = XVECEXP (x, 0, 1);
870 if (as == ADDR_SPACE_GENERIC
871 && GET_MODE (x) == SImode)
872 return false;
874 if (! characterize_address (x, &base, &index, &addend))
875 return false;
877 /* We can't extract the high/low portions of a PLUS address
878 involving a register during devirtualization, so make sure all
879 such __far addresses do not have addends. This forces GCC to do
880 the sum separately. */
881 if (addend && base && as == ADDR_SPACE_FAR)
882 return false;
884 if (base && index)
886 int ir = REGNO (index);
887 int br = REGNO (base);
889 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
890 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
891 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
892 return false;
895 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
896 return false;
898 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
899 && REGNO (base) >= 8 && REGNO (base) <= 31)
900 return false;
902 return true;
905 /* Determine if one named address space is a subset of another. */
906 #undef TARGET_ADDR_SPACE_SUBSET_P
907 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
908 static bool
909 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
911 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
912 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
914 if (subset == superset)
915 return true;
917 else
918 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
921 #undef TARGET_ADDR_SPACE_CONVERT
922 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
923 /* Convert from one address space to another. */
924 static rtx
925 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
927 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
928 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
929 rtx result;
931 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
932 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
934 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
936 /* This is unpredictable, as we're truncating off usable address
937 bits. */
939 result = gen_reg_rtx (HImode);
940 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
941 return result;
943 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
945 /* This always works. */
946 result = gen_reg_rtx (SImode);
947 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
948 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
949 return result;
951 else
952 gcc_unreachable ();
955 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
956 bool
957 rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
958 addr_space_t address_space ATTRIBUTE_UNUSED,
959 int outer_code ATTRIBUTE_UNUSED, int index_code)
961 if (regno <= SP_REG && regno >= 16)
962 return true;
963 if (index_code == REG)
964 return (regno == HL_REG);
965 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
966 return true;
967 return false;
970 /* Implements MODE_CODE_BASE_REG_CLASS. */
971 enum reg_class
972 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
973 addr_space_t address_space ATTRIBUTE_UNUSED,
974 int outer_code ATTRIBUTE_UNUSED,
975 int index_code ATTRIBUTE_UNUSED)
977 return V_REGS;
980 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
981 described in the machine_Function struct definition, above. */
983 rl78_initial_elimination_offset (int from, int to)
985 int rv = 0; /* as if arg to arg */
987 rl78_compute_frame_info ();
989 switch (to)
991 case STACK_POINTER_REGNUM:
992 rv += cfun->machine->framesize_outgoing;
993 rv += cfun->machine->framesize_locals;
994 /* Fall through. */
995 case FRAME_POINTER_REGNUM:
996 rv += cfun->machine->framesize_regs;
997 rv += 4;
998 break;
999 default:
1000 gcc_unreachable ();
1003 switch (from)
1005 case FRAME_POINTER_REGNUM:
1006 rv -= 4;
1007 rv -= cfun->machine->framesize_regs;
1008 case ARG_POINTER_REGNUM:
1009 break;
1010 default:
1011 gcc_unreachable ();
1014 return rv;
1017 static int
1018 rl78_is_naked_func (void)
1020 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1023 /* Expand the function prologue (from the prologue pattern). */
1024 void
1025 rl78_expand_prologue (void)
1027 int i, fs;
1028 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1029 int rb = 0;
1031 if (rl78_is_naked_func ())
1032 return;
1034 /* Always re-compute the frame info - the register usage may have changed. */
1035 rl78_compute_frame_info ();
1037 if (flag_stack_usage_info)
1038 current_function_static_stack_size = cfun->machine->framesize;
1040 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1041 for (i = 0; i < 4; i++)
1042 if (cfun->machine->need_to_push [i])
1044 /* Select Bank 0 if we are using any registers from Bank 0. */
1045 emit_insn (gen_sel_rb (GEN_INT (0)));
1046 break;
1049 for (i = 0; i < 16; i++)
1050 if (cfun->machine->need_to_push [i])
1052 if (TARGET_G10)
1054 emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
1055 F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
1057 else {
1058 int need_bank = i/4;
1059 if (need_bank != rb)
1061 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1062 rb = need_bank;
1064 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
1067 if (rb != 0)
1068 emit_insn (gen_sel_rb (GEN_INT (0)));
1070 if (frame_pointer_needed)
1072 F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1073 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
1074 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
1075 gen_rtx_REG (HImode, AX_REG)));
1078 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1079 while (fs > 0)
1081 int fs_byte = (fs > 254) ? 254 : fs;
1082 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1083 fs -= fs_byte;
1087 /* Expand the function epilogue (from the epilogue pattern). */
1088 void
1089 rl78_expand_epilogue (void)
1091 int i, fs;
1092 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1093 int rb = 0;
1095 if (rl78_is_naked_func ())
1096 return;
1098 if (frame_pointer_needed)
1100 emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1101 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1102 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
1103 gen_rtx_REG (HImode, AX_REG));
1105 else
1107 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1108 while (fs > 0)
1110 int fs_byte = (fs > 254) ? 254 : fs;
1112 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1113 fs -= fs_byte;
1117 for (i = 15; i >= 0; i--)
1118 if (cfun->machine->need_to_push [i])
1120 if (TARGET_G10)
1122 emit_insn (gen_pop (gen_rtx_REG (HImode, 0)));
1123 emit_move_insn (gen_rtx_REG (HImode, i*2), gen_rtx_REG (HImode, 0));
1125 else
1127 int need_bank = i / 4;
1129 if (need_bank != rb)
1131 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1132 rb = need_bank;
1134 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
1138 if (rb != 0)
1139 emit_insn (gen_sel_rb (GEN_INT (0)));
1141 if (cfun->machine->trampolines_used)
1142 emit_insn (gen_trampoline_uninit ());
1144 if (is_brk_interrupt_func (cfun->decl))
1145 emit_jump_insn (gen_brk_interrupt_return ());
1146 else if (is_interrupt_func (cfun->decl))
1147 emit_jump_insn (gen_interrupt_return ());
1148 else
1149 emit_jump_insn (gen_rl78_return ());
1152 /* Likewise, for exception handlers. */
1153 void
1154 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1156 /* FIXME - replace this with an indirect jump with stack adjust. */
1157 emit_jump_insn (gen_rl78_return ());
1160 #undef TARGET_ASM_FUNCTION_PROLOGUE
1161 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1163 /* We don't use this to actually emit the function prologue. We use
1164 this to insert a comment in the asm file describing the
1165 function. */
1166 static void
1167 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1169 int i;
1171 if (cfun->machine->framesize == 0)
1172 return;
1173 fprintf (file, "\t; start of function\n");
1175 if (cfun->machine->framesize_regs)
1177 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1178 for (i = 0; i < 16; i ++)
1179 if (cfun->machine->need_to_push[i])
1180 fprintf (file, " %s", word_regnames[i*2]);
1181 fprintf (file, "\n");
1184 if (frame_pointer_needed)
1185 fprintf (file, "\t; $fp points here (r22)\n");
1187 if (cfun->machine->framesize_locals)
1188 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1189 cfun->machine->framesize_locals == 1 ? "" : "s");
1191 if (cfun->machine->framesize_outgoing)
1192 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1193 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1196 /* Return an RTL describing where a function return value of type RET_TYPE
1197 is held. */
1199 #undef TARGET_FUNCTION_VALUE
1200 #define TARGET_FUNCTION_VALUE rl78_function_value
1202 static rtx
1203 rl78_function_value (const_tree ret_type,
1204 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1205 bool outgoing ATTRIBUTE_UNUSED)
1207 enum machine_mode mode = TYPE_MODE (ret_type);
1209 return gen_rtx_REG (mode, 8);
1212 #undef TARGET_PROMOTE_FUNCTION_MODE
1213 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1215 static enum machine_mode
1216 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1217 enum machine_mode mode,
1218 int *punsignedp ATTRIBUTE_UNUSED,
1219 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1221 return mode;
1224 /* Return an RTL expression describing the register holding a function
1225 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1226 be passed on the stack. CUM describes the previous parameters to the
1227 function and NAMED is false if the parameter is part of a variable
1228 parameter list, or the last named parameter before the start of a
1229 variable parameter list. */
1231 #undef TARGET_FUNCTION_ARG
1232 #define TARGET_FUNCTION_ARG rl78_function_arg
1234 static rtx
1235 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1236 enum machine_mode mode ATTRIBUTE_UNUSED,
1237 const_tree type ATTRIBUTE_UNUSED,
1238 bool named ATTRIBUTE_UNUSED)
1240 return NULL_RTX;
1243 #undef TARGET_FUNCTION_ARG_ADVANCE
1244 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1246 static void
1247 rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1248 bool named ATTRIBUTE_UNUSED)
1250 int rounded_size;
1251 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1253 rounded_size = ((mode == BLKmode)
1254 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1255 if (rounded_size & 1)
1256 rounded_size ++;
1257 (*cum) += rounded_size;
1260 #undef TARGET_FUNCTION_ARG_BOUNDARY
1261 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1263 static unsigned int
1264 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1265 const_tree type ATTRIBUTE_UNUSED)
1267 return 16;
1270 /* Supported modifier letters:
1272 A - address of a MEM
1273 S - SADDR form of a real register
1274 v - real register corresponding to a virtual register
1275 m - minus - negative of CONST_INT value.
1276 c - inverse of a conditional (NE vs EQ for example)
1277 z - collapsed conditional
1278 s - shift count mod 8
1279 S - shift count mod 16
1280 r - reverse shift count (8-(count mod 8))
1282 h - bottom HI of an SI
1283 H - top HI of an SI
1284 q - bottom QI of an HI
1285 Q - top QI of an HI
1286 e - third QI of an SI (i.e. where the ES register gets values from)
1287 E - fourth QI of an SI (i.e. MSB)
1291 /* Implements the bulk of rl78_print_operand, below. We do it this
1292 way because we need to test for a constant at the top level and
1293 insert the '#', but not test for it anywhere else as we recurse
1294 down into the operand. */
1295 static void
1296 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1298 int need_paren;
1300 switch (GET_CODE (op))
1302 case MEM:
1303 if (letter == 'A')
1304 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1305 else
1307 if (rl78_far_p (op))
1309 fprintf (file, "es:");
1310 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1312 if (letter == 'H')
1314 op = adjust_address (op, HImode, 2);
1315 letter = 0;
1317 if (letter == 'h')
1319 op = adjust_address (op, HImode, 0);
1320 letter = 0;
1322 if (letter == 'Q')
1324 op = adjust_address (op, QImode, 1);
1325 letter = 0;
1327 if (letter == 'q')
1329 op = adjust_address (op, QImode, 0);
1330 letter = 0;
1332 if (letter == 'e')
1334 op = adjust_address (op, QImode, 2);
1335 letter = 0;
1337 if (letter == 'E')
1339 op = adjust_address (op, QImode, 3);
1340 letter = 0;
1342 if (CONSTANT_P (XEXP (op, 0)))
1344 fprintf (file, "!");
1345 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1347 else if (GET_CODE (XEXP (op, 0)) == PLUS
1348 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1350 fprintf (file, "!");
1351 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1353 else if (GET_CODE (XEXP (op, 0)) == PLUS
1354 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1355 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1357 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1358 fprintf (file, "[");
1359 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1360 fprintf (file, "]");
1362 else
1364 fprintf (file, "[");
1365 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1366 fprintf (file, "]");
1369 break;
1371 case REG:
1372 if (letter == 'Q')
1373 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1374 else if (letter == 'H')
1375 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1376 else if (letter == 'q')
1377 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1378 else if (letter == 'e')
1379 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1380 else if (letter == 'E')
1381 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1382 else if (letter == 'S')
1383 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1384 else if (GET_MODE (op) == HImode
1385 && ! (REGNO (op) & ~0xfe))
1387 if (letter == 'v')
1388 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1389 else
1390 fprintf (file, "%s", word_regnames [REGNO (op)]);
1392 else
1393 fprintf (file, "%s", reg_names [REGNO (op)]);
1394 break;
1396 case CONST_INT:
1397 if (letter == 'Q')
1398 fprintf (file, "%ld", INTVAL (op) >> 8);
1399 else if (letter == 'H')
1400 fprintf (file, "%ld", INTVAL (op) >> 16);
1401 else if (letter == 'q')
1402 fprintf (file, "%ld", INTVAL (op) & 0xff);
1403 else if (letter == 'h')
1404 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1405 else if (letter == 'e')
1406 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1407 else if (letter == 'E')
1408 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1409 else if (letter == 'm')
1410 fprintf (file, "%ld", - INTVAL (op));
1411 else if (letter == 's')
1412 fprintf (file, "%ld", INTVAL (op) % 8);
1413 else if (letter == 'S')
1414 fprintf (file, "%ld", INTVAL (op) % 16);
1415 else if (letter == 'r')
1416 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1417 else if (letter == 'C')
1418 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1419 else
1420 fprintf (file, "%ld", INTVAL (op));
1421 break;
1423 case CONST:
1424 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1425 break;
1427 case ZERO_EXTRACT:
1429 int bits = INTVAL (XEXP (op, 1));
1430 int ofs = INTVAL (XEXP (op, 2));
1431 if (bits == 16 && ofs == 0)
1432 fprintf (file, "%%lo16(");
1433 else if (bits == 16 && ofs == 16)
1434 fprintf (file, "%%hi16(");
1435 else if (bits == 8 && ofs == 16)
1436 fprintf (file, "%%hi8(");
1437 else
1438 gcc_unreachable ();
1439 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1440 fprintf (file, ")");
1442 break;
1444 case ZERO_EXTEND:
1445 if (GET_CODE (XEXP (op, 0)) == REG)
1446 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1447 else
1448 print_rtl (file, op);
1449 break;
1451 case PLUS:
1452 need_paren = 0;
1453 if (letter == 'H')
1455 fprintf (file, "%%hi16(");
1456 need_paren = 1;
1457 letter = 0;
1459 if (letter == 'h')
1461 fprintf (file, "%%lo16(");
1462 need_paren = 1;
1463 letter = 0;
1465 if (letter == 'e')
1467 fprintf (file, "%%hi8(");
1468 need_paren = 1;
1469 letter = 0;
1471 if (letter == 'q' || letter == 'Q')
1472 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1474 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1476 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1477 fprintf (file, "+");
1478 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1480 else
1482 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1483 fprintf (file, "+");
1484 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1486 if (need_paren)
1487 fprintf (file, ")");
1488 break;
1490 case SYMBOL_REF:
1491 need_paren = 0;
1492 if (letter == 'H')
1494 fprintf (file, "%%hi16(");
1495 need_paren = 1;
1496 letter = 0;
1498 if (letter == 'h')
1500 fprintf (file, "%%lo16(");
1501 need_paren = 1;
1502 letter = 0;
1504 if (letter == 'e')
1506 fprintf (file, "%%hi8(");
1507 need_paren = 1;
1508 letter = 0;
1510 if (letter == 'q' || letter == 'Q')
1511 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1513 output_addr_const (file, op);
1514 if (need_paren)
1515 fprintf (file, ")");
1516 break;
1518 case CODE_LABEL:
1519 case LABEL_REF:
1520 output_asm_label (op);
1521 break;
1523 case LTU:
1524 if (letter == 'z')
1525 fprintf (file, "#comparison eliminated");
1526 else
1527 fprintf (file, letter == 'c' ? "nc" : "c");
1528 break;
1529 case LEU:
1530 if (letter == 'z')
1531 fprintf (file, "br");
1532 else
1533 fprintf (file, letter == 'c' ? "h" : "nh");
1534 break;
1535 case GEU:
1536 if (letter == 'z')
1537 fprintf (file, "br");
1538 else
1539 fprintf (file, letter == 'c' ? "c" : "nc");
1540 break;
1541 case GTU:
1542 if (letter == 'z')
1543 fprintf (file, "#comparison eliminated");
1544 else
1545 fprintf (file, letter == 'c' ? "nh" : "h");
1546 break;
1547 case EQ:
1548 if (letter == 'z')
1549 fprintf (file, "br");
1550 else
1551 fprintf (file, letter == 'c' ? "nz" : "z");
1552 break;
1553 case NE:
1554 if (letter == 'z')
1555 fprintf (file, "#comparison eliminated");
1556 else
1557 fprintf (file, letter == 'c' ? "z" : "nz");
1558 break;
1560 /* Note: these assume appropriate adjustments were made so that
1561 unsigned comparisons, which is all this chip has, will
1562 work. */
1563 case LT:
1564 if (letter == 'z')
1565 fprintf (file, "#comparison eliminated");
1566 else
1567 fprintf (file, letter == 'c' ? "nc" : "c");
1568 break;
1569 case LE:
1570 if (letter == 'z')
1571 fprintf (file, "br");
1572 else
1573 fprintf (file, letter == 'c' ? "h" : "nh");
1574 break;
1575 case GE:
1576 if (letter == 'z')
1577 fprintf (file, "br");
1578 else
1579 fprintf (file, letter == 'c' ? "c" : "nc");
1580 break;
1581 case GT:
1582 if (letter == 'z')
1583 fprintf (file, "#comparison eliminated");
1584 else
1585 fprintf (file, letter == 'c' ? "nh" : "h");
1586 break;
1588 default:
1589 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1590 break;
1594 #undef TARGET_PRINT_OPERAND
1595 #define TARGET_PRINT_OPERAND rl78_print_operand
1597 static void
1598 rl78_print_operand (FILE * file, rtx op, int letter)
1600 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S')
1601 fprintf (file, "#");
1602 rl78_print_operand_1 (file, op, letter);
1605 #undef TARGET_TRAMPOLINE_INIT
1606 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1608 /* Note that the RL78's addressing makes it very difficult to do
1609 trampolines on the stack. So, libgcc has a small pool of
1610 trampolines from which one is allocated to this task. */
1611 static void
1612 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1614 rtx mov_addr, thunk_addr;
1615 rtx function = XEXP (DECL_RTL (fndecl), 0);
1617 mov_addr = adjust_address (m_tramp, HImode, 0);
1618 thunk_addr = gen_reg_rtx (HImode);
1620 function = force_reg (HImode, function);
1621 static_chain = force_reg (HImode, static_chain);
1623 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1624 emit_move_insn (mov_addr, thunk_addr);
1626 cfun->machine->trampolines_used = 1;
1629 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1630 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1632 static rtx
1633 rl78_trampoline_adjust_address (rtx m_tramp)
1635 rtx x = gen_rtx_MEM (HImode, m_tramp);
1636 return x;
1639 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1640 the "normal" compares, specifically, it only has unsigned compares,
1641 so we must synthesize the missing ones. */
1642 void
1643 rl78_expand_compare (rtx *operands)
1645 if (GET_CODE (operands[2]) == MEM)
1646 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1651 /* Define this to 1 if you are debugging the peephole optimizers. */
1652 #define DEBUG_PEEP 0
1654 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1655 The default "word" size is a byte so we can effectively use all the
1656 registers, but we want to do 16-bit moves whenever possible. This
1657 function determines when such a move is an option. */
1658 bool
1659 rl78_peep_movhi_p (rtx *operands)
1661 int i;
1662 rtx m, a;
1664 /* (set (op0) (op1))
1665 (set (op2) (op3)) */
1667 #if DEBUG_PEEP
1668 fprintf (stderr, "\033[33m");
1669 debug_rtx (operands[0]);
1670 debug_rtx (operands[1]);
1671 debug_rtx (operands[2]);
1672 debug_rtx (operands[3]);
1673 fprintf (stderr, "\033[0m");
1674 #endif
1676 /* You can move a constant to memory as QImode, but not HImode. */
1677 if (GET_CODE (operands[0]) == MEM
1678 && GET_CODE (operands[1]) != REG)
1680 #if DEBUG_PEEP
1681 fprintf (stderr, "no peep: move constant to memory\n");
1682 #endif
1683 return false;
1686 if (rtx_equal_p (operands[0], operands[3]))
1688 #if DEBUG_PEEP
1689 fprintf (stderr, "no peep: overlapping\n");
1690 #endif
1691 return false;
1694 for (i = 0; i < 2; i ++)
1696 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1698 #if DEBUG_PEEP
1699 fprintf (stderr, "no peep: different codes\n");
1700 #endif
1701 return false;
1703 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1705 #if DEBUG_PEEP
1706 fprintf (stderr, "no peep: different modes\n");
1707 #endif
1708 return false;
1711 switch (GET_CODE (operands[i]))
1713 case REG:
1714 /* LSB MSB */
1715 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1716 || GET_MODE (operands[i]) != QImode)
1718 #if DEBUG_PEEP
1719 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1720 REGNO (operands[i]), REGNO (operands[i+2]),
1722 #endif
1723 return false;
1725 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1727 #if DEBUG_PEEP
1728 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1729 #endif
1730 return false;
1732 break;
1734 case CONST_INT:
1735 break;
1737 case MEM:
1738 if (GET_MODE (operands[i]) != QImode)
1739 return false;
1740 if (MEM_ALIGN (operands[i]) < 16)
1741 return false;
1742 a = XEXP (operands[i], 0);
1743 if (GET_CODE (a) == CONST)
1744 a = XEXP (a, 0);
1745 if (GET_CODE (a) == PLUS)
1746 a = XEXP (a, 1);
1747 if (GET_CODE (a) == CONST_INT
1748 && INTVAL (a) & 1)
1750 #if DEBUG_PEEP
1751 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1752 debug_rtx (operands[i]);
1753 #endif
1754 return false;
1756 m = adjust_address (operands[i], QImode, 1);
1757 if (! rtx_equal_p (m, operands[i+2]))
1759 #if DEBUG_PEEP
1760 fprintf (stderr, "no peep: wrong mem %d\n", i);
1761 debug_rtx(m);
1762 debug_rtx (operands[i+2]);
1763 #endif
1764 return false;
1766 break;
1768 default:
1769 #if DEBUG_PEEP
1770 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1771 #endif
1772 return false;
1775 #if DEBUG_PEEP
1776 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1777 #endif
1778 return true;
1781 /* Likewise, when a peephole is activated, this function helps compute
1782 the new operands. */
1783 void
1784 rl78_setup_peep_movhi (rtx *operands)
1786 int i;
1788 for (i = 0; i < 2; i ++)
1790 switch (GET_CODE (operands[i]))
1792 case REG:
1793 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1794 break;
1796 case CONST_INT:
1797 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1798 break;
1800 case MEM:
1801 operands[i+4] = adjust_address (operands[i], HImode, 0);
1802 break;
1804 default:
1805 break;
1811 How Devirtualization works in the RL78 GCC port
1813 Background
1815 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1816 bytes of register space, in four banks, memory-mapped. One bank is
1817 the "selected" bank and holds the registers used for primary
1818 operations. Since the registers are memory mapped, often you can
1819 still refer to the unselected banks via memory accesses.
1821 Virtual Registers
1823 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1824 and refers to the other banks via their memory addresses, although
1825 they're treated as regular registers internally. These "virtual"
1826 registers are R8 through R23 (bank3 is reserved for asm-based
1827 interrupt handlers).
1829 There are four machine description files:
1831 rl78.md - common register-independent patterns and definitions
1832 rl78-expand.md - expanders
1833 rl78-virt.md - patterns that match BEFORE devirtualization
1834 rl78-real.md - patterns that match AFTER devirtualization
1836 At least through register allocation and reload, gcc is told that it
1837 can do pretty much anything - but may only use the virtual registers.
1838 GCC cannot properly create the varying addressing modes that the RL78
1839 supports in an efficient way.
1841 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1842 uses the "valloc" attribute in rl78-virt.md for determining the rules
1843 by which it will replace virtual registers with real registers (or
1844 not) and how to make up addressing modes. For example, insns tagged
1845 with "ro1" have a single read-only parameter, which may need to be
1846 moved from memory/constant/vreg to a suitable real register. As part
1847 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1848 patterns and enabling the rl78-real.md patterns. The new patterns'
1849 constraints are used to determine the real registers used. NOTE:
1850 patterns in rl78-virt.md essentially ignore the constrains and rely on
1851 predicates, where the rl78-real.md ones essentially ignore the
1852 predicates and rely on the constraints.
1854 The devirtualization pass is scheduled via the pass manager (despite
1855 being called "rl78_reorg") so it can be scheduled prior to var-track
1856 (the idea is to let gdb know about the new registers). Ideally, it
1857 would be scheduled right after pro/epilogue generation, so the
1858 post-reload optimizers could operate on the real registers, but when I
1859 tried that there were some issues building the target libraries.
1861 During devirtualization, a simple register move optimizer is run. It
1862 would be better to run a full CSE/propogation pass on it through, or
1863 re-run regmove, but that has not yet been attempted.
1866 #define DEBUG_ALLOC 0
1868 #define OP(x) (*recog_data.operand_loc[x])
1870 /* This array is used to hold knowledge about the contents of the
1871 real registers (A ... H), the memory-based registers (r8 ... r31)
1872 and the first NUM_STACK_LOCS words on the stack. We use this to
1873 avoid generating redundant move instructions.
1875 A value in the range 0 .. 31 indicates register A .. r31.
1876 A value in the range 32 .. 63 indicates stack slot (value - 32).
1877 A value of NOT_KNOWN indicates that the contents of that location
1878 are not known. */
1880 #define NUM_STACK_LOCS 32
1881 #define NOT_KNOWN 127
1883 static unsigned char content_memory [32 + NUM_STACK_LOCS];
1885 static unsigned char saved_update_index = NOT_KNOWN;
1886 static unsigned char saved_update_value;
1887 static enum machine_mode saved_update_mode;
1890 static inline void
1891 clear_content_memory (void)
1893 memset (content_memory, NOT_KNOWN, sizeof content_memory);
1894 if (dump_file)
1895 fprintf (dump_file, " clear content memory\n");
1896 saved_update_index = NOT_KNOWN;
1899 /* Convert LOC into an index into the content_memory array.
1900 If LOC cannot be converted, return NOT_KNOWN. */
1902 static unsigned char
1903 get_content_index (rtx loc)
1905 enum machine_mode mode;
1907 if (loc == NULL_RTX)
1908 return NOT_KNOWN;
1910 if (REG_P (loc))
1912 if (REGNO (loc) < 32)
1913 return REGNO (loc);
1914 return NOT_KNOWN;
1917 mode = GET_MODE (loc);
1919 if (! rl78_stack_based_mem (loc, mode))
1920 return NOT_KNOWN;
1922 loc = XEXP (loc, 0);
1924 if (REG_P (loc))
1925 /* loc = MEM (SP) */
1926 return 32;
1928 /* loc = MEM (PLUS (SP, INT)). */
1929 loc = XEXP (loc, 1);
1931 if (INTVAL (loc) < NUM_STACK_LOCS)
1932 return 32 + INTVAL (loc);
1934 return NOT_KNOWN;
1937 /* Return a string describing content INDEX in mode MODE.
1938 WARNING: Can return a pointer to a static buffer. */
1940 static const char *
1941 get_content_name (unsigned char index, enum machine_mode mode)
1943 static char buffer [128];
1945 if (index == NOT_KNOWN)
1946 return "Unknown";
1948 if (index > 31)
1949 sprintf (buffer, "stack slot %d", index - 32);
1950 else if (mode == HImode)
1951 sprintf (buffer, "%s%s",
1952 reg_names [index + 1], reg_names [index]);
1953 else
1954 return reg_names [index];
1956 return buffer;
1959 #if DEBUG_ALLOC
1961 static void
1962 display_content_memory (FILE * file)
1964 unsigned int i;
1966 fprintf (file, " Known memory contents:\n");
1968 for (i = 0; i < sizeof content_memory; i++)
1969 if (content_memory[i] != NOT_KNOWN)
1971 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
1972 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
1975 #endif
1977 static void
1978 update_content (unsigned char index, unsigned char val, enum machine_mode mode)
1980 unsigned int i;
1982 gcc_assert (index < sizeof content_memory);
1984 content_memory [index] = val;
1985 if (val != NOT_KNOWN)
1986 content_memory [val] = index;
1988 /* Make the entry in dump_file *before* VAL is increased below. */
1989 if (dump_file)
1991 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
1992 if (val == NOT_KNOWN)
1993 fprintf (dump_file, "Unknown\n");
1994 else
1995 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
1998 if (mode == HImode)
2000 val = val == NOT_KNOWN ? val : val + 1;
2002 content_memory [index + 1] = val;
2003 if (val != NOT_KNOWN)
2005 content_memory [val] = index + 1;
2006 -- val;
2010 /* Any other places that had INDEX recorded as their contents are now invalid. */
2011 for (i = 0; i < sizeof content_memory; i++)
2013 if (i == index
2014 || (val != NOT_KNOWN && i == val))
2016 if (mode == HImode)
2017 ++ i;
2018 continue;
2021 if (content_memory[i] == index
2022 || (val != NOT_KNOWN && content_memory[i] == val))
2024 content_memory[i] = NOT_KNOWN;
2026 if (dump_file)
2027 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2029 if (mode == HImode)
2030 content_memory[++ i] = NOT_KNOWN;
2035 /* Record that LOC contains VALUE.
2036 For HImode locations record that LOC+1 contains VALUE+1.
2037 If LOC is not a register or stack slot, do nothing.
2038 If VALUE is not a register or stack slot, clear the recorded content. */
2040 static void
2041 record_content (rtx loc, rtx value)
2043 enum machine_mode mode;
2044 unsigned char index;
2045 unsigned char val;
2047 if ((index = get_content_index (loc)) == NOT_KNOWN)
2048 return;
2050 val = get_content_index (value);
2052 mode = GET_MODE (loc);
2054 if (val == index)
2056 if (! optimize)
2057 return;
2059 /* This should not happen when optimizing. */
2060 #if 1
2061 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2062 get_content_name (val, mode));
2063 return;
2064 #else
2065 gcc_unreachable ();
2066 #endif
2069 update_content (index, val, mode);
2072 /* Returns TRUE if LOC already contains a copy of VALUE. */
2074 static bool
2075 already_contains (rtx loc, rtx value)
2077 unsigned char index;
2078 unsigned char val;
2080 if ((index = get_content_index (loc)) == NOT_KNOWN)
2081 return false;
2083 if ((val = get_content_index (value)) == NOT_KNOWN)
2084 return false;
2086 if (content_memory [index] != val)
2087 return false;
2089 if (GET_MODE (loc) == HImode)
2090 return content_memory [index + 1] == val + 1;
2092 return true;
2095 bool
2096 rl78_es_addr (rtx addr)
2098 if (GET_CODE (addr) == MEM)
2099 addr = XEXP (addr, 0);
2100 if (GET_CODE (addr) != UNSPEC)
2101 return false;
2102 if (XINT (addr, 1) != UNS_ES_ADDR)
2103 return false;
2104 return true;
2108 rl78_es_base (rtx addr)
2110 if (GET_CODE (addr) == MEM)
2111 addr = XEXP (addr, 0);
2112 addr = XVECEXP (addr, 0, 1);
2113 if (GET_CODE (addr) == CONST
2114 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2115 addr = XEXP (XEXP (addr, 0), 0);
2116 /* Mode doesn't matter here. */
2117 return gen_rtx_MEM (HImode, addr);
2120 /* Rescans an insn to see if it's recognized again. This is done
2121 carefully to ensure that all the constraint information is accurate
2122 for the newly matched insn. */
2123 static bool
2124 insn_ok_now (rtx insn)
2126 rtx pattern = PATTERN (insn);
2127 int i;
2129 INSN_CODE (insn) = -1;
2131 if (recog (pattern, insn, 0) > -1)
2133 extract_insn (insn);
2134 if (constrain_operands (1))
2136 #if DEBUG_ALLOC
2137 fprintf (stderr, "\033[32m");
2138 debug_rtx (insn);
2139 fprintf (stderr, "\033[0m");
2140 #endif
2141 if (SET_P (pattern))
2142 record_content (SET_DEST (pattern), SET_SRC (pattern));
2144 /* We need to detect far addresses that haven't been
2145 converted to es/lo16 format. */
2146 for (i=0; i<recog_data.n_operands; i++)
2147 if (GET_CODE (OP(i)) == MEM
2148 && GET_MODE (XEXP (OP(i), 0)) == SImode
2149 && GET_CODE (XEXP (OP(i), 0)) != UNSPEC)
2150 return false;
2152 return true;
2155 else
2157 /* We need to re-recog the insn with virtual registers to get
2158 the operands */
2159 cfun->machine->virt_insns_ok = 1;
2160 if (recog (pattern, insn, 0) > -1)
2162 extract_insn (insn);
2163 if (constrain_operands (0))
2165 cfun->machine->virt_insns_ok = 0;
2166 return false;
2170 #if DEBUG_ALLOC
2171 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2172 debug_rtx (insn);
2173 #endif
2174 gcc_unreachable ();
2177 #if DEBUG_ALLOC
2178 fprintf (stderr, "\033[31m");
2179 debug_rtx (insn);
2180 fprintf (stderr, "\033[0m");
2181 #endif
2182 return false;
2185 #if DEBUG_ALLOC
2186 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2187 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2188 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2189 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2190 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2191 #else
2192 #define FAILED gcc_unreachable ()
2193 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2194 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2195 #endif
2197 /* Registers into which we move the contents of virtual registers. */
2198 #define X gen_rtx_REG (QImode, 0)
2199 #define A gen_rtx_REG (QImode, 1)
2200 #define C gen_rtx_REG (QImode, 2)
2201 #define B gen_rtx_REG (QImode, 3)
2202 #define E gen_rtx_REG (QImode, 4)
2203 #define D gen_rtx_REG (QImode, 5)
2204 #define L gen_rtx_REG (QImode, 6)
2205 #define H gen_rtx_REG (QImode, 7)
2207 #define AX gen_rtx_REG (HImode, 0)
2208 #define BC gen_rtx_REG (HImode, 2)
2209 #define DE gen_rtx_REG (HImode, 4)
2210 #define HL gen_rtx_REG (HImode, 6)
2212 /* Returns TRUE if R is a virtual register. */
2213 static bool
2214 is_virtual_register (rtx r)
2216 return (GET_CODE (r) == REG
2217 && REGNO (r) >= 8
2218 && REGNO (r) < 24);
2221 /* In all these alloc routines, we expect the following: the insn
2222 pattern is unshared, the insn was previously recognized and failed
2223 due to predicates or constraints, and the operand data is in
2224 recog_data. */
2226 static int virt_insn_was_frame;
2228 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2229 needed. */
2230 static rtx
2231 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2233 #if DEBUG_ALLOC
2234 fprintf (stderr, "\033[36m%d: ", line);
2235 debug_rtx(r);
2236 fprintf (stderr, "\033[0m");
2237 #endif
2238 /*SCHED_GROUP_P (r) = 1;*/
2239 if (virt_insn_was_frame)
2240 RTX_FRAME_RELATED_P (r) = 1;
2241 return r;
2244 #define EM(x) EM2 (__LINE__, x)
2246 /* Return a suitable RTX for the low half of a __far address. */
2247 static rtx
2248 rl78_lo16 (rtx addr)
2250 rtx r;
2252 if (GET_CODE (addr) == SYMBOL_REF
2253 || GET_CODE (addr) == CONST)
2255 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2256 r = gen_rtx_CONST (HImode, r);
2258 else
2259 r = rl78_subreg (HImode, addr, SImode, 0);
2261 r = gen_es_addr (r);
2263 return r;
2266 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2267 static rtx
2268 rl78_hi8 (rtx addr)
2270 if (GET_CODE (addr) == SYMBOL_REF
2271 || GET_CODE (addr) == CONST)
2273 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2274 r = gen_rtx_CONST (QImode, r);
2275 return r;
2277 return rl78_subreg (QImode, addr, SImode, 2);
2280 static void
2281 add_postponed_content_update (rtx to, rtx value)
2283 unsigned char index;
2285 if ((index = get_content_index (to)) == NOT_KNOWN)
2286 return;
2288 gcc_assert (saved_update_index == NOT_KNOWN);
2289 saved_update_index = index;
2290 saved_update_value = get_content_index (value);
2291 saved_update_mode = GET_MODE (to);
2294 static void
2295 process_postponed_content_update (void)
2297 if (saved_update_index != NOT_KNOWN)
2299 update_content (saved_update_index, saved_update_value, saved_update_mode);
2300 saved_update_index = NOT_KNOWN;
2304 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2305 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2306 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2307 BEFORE is true, FROM otherwise. */
2308 static rtx
2309 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2311 enum machine_mode mode = GET_MODE (to);
2313 if (optimize && before && already_contains (to, from))
2315 #if DEBUG_ALLOC
2316 display_content_memory (stderr);
2317 #endif
2318 if (dump_file)
2320 fprintf (dump_file, " Omit move of %s into ",
2321 get_content_name (get_content_index (from), mode));
2322 fprintf (dump_file, "%s as it already contains this value\n",
2323 get_content_name (get_content_index (to), mode));
2326 else
2328 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2330 EM (move);
2332 if (where == NULL_RTX)
2333 emit_insn (move);
2334 else if (before)
2335 emit_insn_before (move, where);
2336 else
2338 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2340 /* If necessary move REG_EH_REGION notes forward.
2341 cf. compiling gcc.dg/pr44545.c. */
2342 if (note != NULL_RTX)
2344 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2345 remove_note (where, note);
2348 emit_insn_after (move, where);
2351 if (before)
2352 record_content (to, from);
2353 else
2354 add_postponed_content_update (to, from);
2356 return before ? to : from;
2359 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2360 copy it into NEWBASE and return the updated MEM. Otherwise just
2361 return M. Any needed insns are emitted before BEFORE. */
2362 static rtx
2363 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2365 rtx base, index, addendr;
2366 int addend = 0;
2367 int need_es = 0;
2369 if (! MEM_P (m))
2370 return m;
2372 if (GET_MODE (XEXP (m, 0)) == SImode)
2374 rtx seg = rl78_hi8 (XEXP (m, 0));
2375 #if DEBUG_ALLOC
2376 fprintf (stderr, "setting ES:\n");
2377 debug_rtx(seg);
2378 #endif
2379 emit_insn_before (EM (gen_movqi (A, seg)), before);
2380 emit_insn_before (EM (gen_movqi_es (A)), before);
2381 record_content (A, NULL_RTX);
2383 m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2384 need_es = 1;
2387 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2388 gcc_assert (index == NULL_RTX);
2390 #if DEBUG_ALLOC
2391 fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m");
2392 debug_rtx (base);
2393 #endif
2394 if (base == NULL_RTX)
2395 return m;
2397 if (addendr && GET_CODE (addendr) == CONST_INT)
2398 addend = INTVAL (addendr);
2400 gcc_assert (REG_P (base));
2401 gcc_assert (REG_P (newbase));
2403 if (REGNO (base) == SP_REG)
2405 if (addend >= 0 && addend <= 255)
2406 return m;
2409 /* BASE should be a virtual register. We copy it to NEWBASE. If
2410 the addend is out of range for DE/HL, we use AX to compute the full
2411 address. */
2413 if (addend < 0
2414 || (addend > 255 && REGNO (newbase) != 2)
2415 || (addendr && GET_CODE (addendr) != CONST_INT))
2417 /* mov ax, vreg
2418 add ax, #imm
2419 mov hl, ax */
2420 EM (emit_insn_before (gen_movhi (AX, base), before));
2421 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2422 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2423 record_content (AX, NULL_RTX);
2424 record_content (newbase, NULL_RTX);
2426 base = newbase;
2427 addend = 0;
2429 else
2431 base = gen_and_emit_move (newbase, base, before, true);
2434 if (addend)
2436 record_content (base, NULL_RTX);
2437 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2440 #if DEBUG_ALLOC
2441 fprintf (stderr, "\033[33m");
2442 debug_rtx (m);
2443 #endif
2444 if (need_es)
2445 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2446 else
2447 m = change_address (m, GET_MODE (m), base);
2448 #if DEBUG_ALLOC
2449 debug_rtx (m);
2450 fprintf (stderr, "\033[0m");
2451 #endif
2452 return m;
2455 /* Copy SRC to accumulator (A or AX), placing any generated insns
2456 before BEFORE. Returns accumulator RTX. */
2458 static rtx
2459 move_to_acc (int opno, rtx before)
2461 rtx src = OP (opno);
2462 enum machine_mode mode = GET_MODE (src);
2464 if (REG_P (src) && REGNO (src) < 2)
2465 return src;
2467 if (mode == VOIDmode)
2468 mode = recog_data.operand_mode[opno];
2470 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2473 static void
2474 force_into_acc (rtx src, rtx before)
2476 enum machine_mode mode = GET_MODE (src);
2477 rtx move;
2479 if (REG_P (src) && REGNO (src) < 2)
2480 return;
2482 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2484 EM (move);
2486 emit_insn_before (move, before);
2487 record_content (AX, NULL_RTX);
2490 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2491 after AFTER. Returns accumulator RTX. */
2493 static rtx
2494 move_from_acc (unsigned int opno, rtx after)
2496 rtx dest = OP (opno);
2497 enum machine_mode mode = GET_MODE (dest);
2499 if (REG_P (dest) && REGNO (dest) < 2)
2500 return dest;
2502 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2505 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2506 before BEFORE. Returns reg RTX. */
2508 static rtx
2509 move_acc_to_reg (rtx acc, int regno, rtx before)
2511 enum machine_mode mode = GET_MODE (acc);
2512 rtx reg;
2514 reg = gen_rtx_REG (mode, regno);
2516 return gen_and_emit_move (reg, acc, before, true);
2519 /* Copy SRC to X, placing any generated insns before BEFORE.
2520 Returns X RTX. */
2522 static rtx
2523 move_to_x (int opno, rtx before)
2525 rtx src = OP (opno);
2526 enum machine_mode mode = GET_MODE (src);
2527 rtx reg;
2529 if (mode == VOIDmode)
2530 mode = recog_data.operand_mode[opno];
2531 reg = (mode == QImode) ? X : AX;
2533 if (mode == QImode || ! is_virtual_register (OP (opno)))
2535 OP (opno) = move_to_acc (opno, before);
2536 OP (opno) = move_acc_to_reg (OP(opno), X_REG, before);
2537 return reg;
2540 return gen_and_emit_move (reg, src, before, true);
2543 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
2544 Returns H/HL RTX. */
2546 static rtx
2547 move_to_hl (int opno, rtx before)
2549 rtx src = OP (opno);
2550 enum machine_mode mode = GET_MODE (src);
2551 rtx reg;
2553 if (mode == VOIDmode)
2554 mode = recog_data.operand_mode[opno];
2555 reg = (mode == QImode) ? L : HL;
2557 if (mode == QImode || ! is_virtual_register (OP (opno)))
2559 OP (opno) = move_to_acc (opno, before);
2560 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2561 return reg;
2564 return gen_and_emit_move (reg, src, before, true);
2567 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
2568 Returns E/DE RTX. */
2570 static rtx
2571 move_to_de (int opno, rtx before)
2573 rtx src = OP (opno);
2574 enum machine_mode mode = GET_MODE (src);
2575 rtx reg;
2577 if (mode == VOIDmode)
2578 mode = recog_data.operand_mode[opno];
2580 reg = (mode == QImode) ? E : DE;
2582 if (mode == QImode || ! is_virtual_register (OP (opno)))
2584 OP (opno) = move_to_acc (opno, before);
2585 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2587 else
2589 gen_and_emit_move (reg, src, before, true);
2592 return reg;
2595 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2596 static void
2597 rl78_alloc_physical_registers_op1 (rtx insn)
2599 /* op[0] = func op[1] */
2601 /* We first try using A as the destination, then copying it
2602 back. */
2603 if (rtx_equal_p (OP (0), OP (1)))
2605 OP (0) =
2606 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2608 else
2610 /* If necessary, load the operands into BC and HL.
2611 Check to see if we already have OP (0) in HL
2612 and if so, swap the order. */
2613 if (MEM_P (OP (0))
2614 && already_contains (HL, XEXP (OP (0), 0)))
2616 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2617 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2619 else
2621 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2622 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2626 MAYBE_OK (insn);
2628 OP (0) = move_from_acc (0, insn);
2630 MAYBE_OK (insn);
2632 /* Try copying the src to acc first, then. This is for, for
2633 example, ZERO_EXTEND or NOT. */
2634 OP (1) = move_to_acc (1, insn);
2636 MUST_BE_OK (insn);
2639 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2640 Assumes that the current insn has already been recognised and hence the
2641 constraint data has been filled in. */
2642 static bool
2643 has_constraint (unsigned int opnum, enum constraint_num constraint)
2645 const char * p = recog_data.constraints[opnum];
2647 /* No constraints means anything is accepted. */
2648 if (p == NULL || *p == 0 || *p == ',')
2649 return true;
2653 char c;
2654 unsigned int len;
2656 c = *p;
2657 len = CONSTRAINT_LEN (c, p);
2658 gcc_assert (len > 0);
2660 switch (c)
2662 case 0:
2663 case ',':
2664 return false;
2665 default:
2666 if (lookup_constraint (p) == constraint)
2667 return true;
2669 p += len;
2671 while (1);
2674 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2675 static void
2676 rl78_alloc_physical_registers_op2 (rtx insn)
2678 rtx prev;
2679 rtx first;
2680 bool hl_used;
2681 int tmp_id;
2682 rtx saved_op1;
2684 if (rtx_equal_p (OP (0), OP (1)))
2686 OP (0) =
2687 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2688 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2690 else if (rtx_equal_p (OP (0), OP (2)))
2692 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2693 OP (0) =
2694 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2696 else
2698 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2699 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2700 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2703 MAYBE_OK (insn);
2705 prev = prev_nonnote_nondebug_insn (insn);
2706 if (recog_data.constraints[1][0] == '%'
2707 && is_virtual_register (OP (1))
2708 && ! is_virtual_register (OP (2))
2709 && ! CONSTANT_P (OP (2)))
2711 rtx tmp = OP (1);
2712 OP (1) = OP (2);
2713 OP (2) = tmp;
2716 /* Make a note of whether (H)L is being used. It matters
2717 because if OP (2) alsoneeds reloading, then we must take
2718 care not to corrupt HL. */
2719 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2721 /* If HL is not currently being used and dest == op1 then there are
2722 some possible optimizations available by reloading one of the
2723 operands into HL, before trying to use the accumulator. */
2724 if (optimize
2725 && ! hl_used
2726 && rtx_equal_p (OP (0), OP (1)))
2728 /* If op0 is a Ws1 type memory address then switching the base
2729 address register to HL might allow us to perform an in-memory
2730 operation. (eg for the INCW instruction).
2732 FIXME: Adding the move into HL is costly if this optimization is not
2733 going to work, so for now, make sure that we know that the new insn will
2734 match the requirements of the addhi3_real pattern. Really we ought to
2735 generate a candidate sequence, test that, and then install it if the
2736 results are good. */
2737 if (satisfies_constraint_Ws1 (OP (0))
2738 && has_constraint (0, CONSTRAINT_Wh1)
2739 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2741 rtx base, index, addend, newbase;
2743 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
2744 gcc_assert (index == NULL_RTX);
2745 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2747 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2748 if (addend != NULL_RTX)
2750 newbase = gen_and_emit_move (HL, base, insn, true);
2751 record_content (newbase, NULL_RTX);
2752 newbase = gen_rtx_PLUS (HImode, newbase, addend);
2754 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
2756 /* We do not want to fail here as this means that
2757 we have inserted useless insns into the stream. */
2758 MUST_BE_OK (insn);
2761 else if (REG_P (OP (0))
2762 && satisfies_constraint_Ws1 (OP (2))
2763 && has_constraint (2, CONSTRAINT_Wh1))
2765 rtx base, index, addend, newbase;
2767 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
2768 gcc_assert (index == NULL_RTX);
2769 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2771 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2772 if (addend != NULL_RTX)
2774 gen_and_emit_move (HL, base, insn, true);
2776 if (REGNO (OP (0)) != X_REG)
2778 OP (1) = move_to_acc (1, insn);
2779 OP (0) = move_from_acc (0, insn);
2782 record_content (HL, NULL_RTX);
2783 newbase = gen_rtx_PLUS (HImode, HL, addend);
2785 OP (2) = change_address (OP (2), VOIDmode, newbase);
2787 /* We do not want to fail here as this means that
2788 we have inserted useless insns into the stream. */
2789 MUST_BE_OK (insn);
2795 OP (0) = move_from_acc (0, insn);
2797 tmp_id = get_max_insn_count ();
2798 saved_op1 = OP (1);
2800 if (rtx_equal_p (OP (1), OP (2)))
2801 OP (2) = OP (1) = move_to_acc (1, insn);
2802 else
2803 OP (1) = move_to_acc (1, insn);
2805 MAYBE_OK (insn);
2807 /* If we omitted the move of OP1 into the accumulator (because
2808 it was already there from a previous insn), then force the
2809 generation of the move instruction now. We know that we
2810 are about to emit a move into HL (or DE) via AX, and hence
2811 our optimization to remove the load of OP1 is no longer valid. */
2812 if (tmp_id == get_max_insn_count ())
2813 force_into_acc (saved_op1, insn);
2815 /* We have to copy op2 to HL (or DE), but that involves AX, which
2816 already has a live value. Emit it before those insns. */
2818 if (prev)
2819 first = next_nonnote_nondebug_insn (prev);
2820 else
2821 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2824 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2826 MUST_BE_OK (insn);
2829 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2831 static void
2832 rl78_alloc_physical_registers_ro1 (rtx insn)
2834 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2836 MAYBE_OK (insn);
2838 OP (0) = move_to_acc (0, insn);
2840 MUST_BE_OK (insn);
2843 /* Devirtualize a compare insn. */
2845 static void
2846 rl78_alloc_physical_registers_cmp (rtx insn)
2848 int tmp_id;
2849 rtx saved_op1;
2850 rtx prev = prev_nonnote_nondebug_insn (insn);
2851 rtx first;
2853 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2854 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2856 /* HI compares have to have OP(1) in AX, but QI
2857 compares do not, so it is worth checking here. */
2858 MAYBE_OK (insn);
2860 /* For an HImode compare, OP(1) must always be in AX.
2861 But if OP(1) is a REG (and not AX), then we can avoid
2862 a reload of OP(1) if we reload OP(2) into AX and invert
2863 the comparison. */
2864 if (REG_P (OP (1))
2865 && REGNO (OP (1)) != AX_REG
2866 && GET_MODE (OP (1)) == HImode
2867 && MEM_P (OP (2)))
2869 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
2871 OP (2) = move_to_acc (2, insn);
2873 switch (GET_CODE (cmp))
2875 case EQ:
2876 case NE:
2877 break;
2878 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
2879 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
2880 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
2881 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
2883 case LT:
2884 case GT:
2885 case LE:
2886 case GE:
2887 #if DEBUG_ALLOC
2888 debug_rtx (insn);
2889 #endif
2890 default:
2891 gcc_unreachable ();
2894 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
2895 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
2896 else
2897 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
2899 MUST_BE_OK (insn);
2902 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2903 should be handled by the second alternative of the cbranchhi_real pattern. */
2904 if (rtx_equal_p (OP (1), OP (2)))
2906 OP (1) = OP (2) = BC;
2907 MUST_BE_OK (insn);
2910 tmp_id = get_max_insn_count ();
2911 saved_op1 = OP (1);
2913 OP (1) = move_to_acc (1, insn);
2915 MAYBE_OK (insn);
2917 /* If we omitted the move of OP1 into the accumulator (because
2918 it was already there from a previous insn), then force the
2919 generation of the move instruction now. We know that we
2920 are about to emit a move into HL via AX, and hence our
2921 optimization to remove the load of OP1 is no longer valid. */
2922 if (tmp_id == get_max_insn_count ())
2923 force_into_acc (saved_op1, insn);
2925 /* We have to copy op2 to HL, but that involves the acc, which
2926 already has a live value. Emit it before those insns. */
2927 if (prev)
2928 first = next_nonnote_nondebug_insn (prev);
2929 else
2930 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2932 OP (2) = move_to_hl (2, first);
2934 MUST_BE_OK (insn);
2937 /* Like op2, but AX = A op X. */
2939 static void
2940 rl78_alloc_physical_registers_umul (rtx insn)
2942 rtx prev = prev_nonnote_nondebug_insn (insn);
2943 rtx first;
2944 int tmp_id;
2945 rtx saved_op1;
2947 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2948 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2949 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2951 MAYBE_OK (insn);
2953 if (recog_data.constraints[1][0] == '%'
2954 && is_virtual_register (OP (1))
2955 && !is_virtual_register (OP (2))
2956 && !CONSTANT_P (OP (2)))
2958 rtx tmp = OP (1);
2959 OP (1) = OP (2);
2960 OP (2) = tmp;
2963 OP (0) = move_from_acc (0, insn);
2965 tmp_id = get_max_insn_count ();
2966 saved_op1 = OP (1);
2968 OP (1) = move_to_acc (1, insn);
2970 MAYBE_OK (insn);
2972 /* If we omitted the move of OP1 into the accumulator (because
2973 it was already there from a previous insn), then force the
2974 generation of the move instruction now. We know that we
2975 are about to emit a move into HL (or DE) via AX, and hence
2976 our optimization to remove the load of OP1 is no longer valid. */
2977 if (tmp_id == get_max_insn_count ())
2978 force_into_acc (saved_op1, insn);
2980 /* We have to copy op2 to X, but that involves the acc, which
2981 already has a live value. Emit it before those insns. */
2983 if (prev)
2984 first = next_nonnote_nondebug_insn (prev);
2985 else
2986 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2988 OP (2) = move_to_x (2, first);
2990 MUST_BE_OK (insn);
2993 static void
2994 rl78_alloc_address_registers_macax (rtx insn)
2996 int which, op;
2997 bool replace_in_op0 = false;
2998 bool replace_in_op1 = false;
3000 MAYBE_OK (insn);
3002 /* Two different MEMs are not allowed. */
3003 which = 0;
3004 for (op = 2; op >= 0; op --)
3006 if (MEM_P (OP (op)))
3008 if (op == 0 && replace_in_op0)
3009 continue;
3010 if (op == 1 && replace_in_op1)
3011 continue;
3013 switch (which)
3015 case 0:
3016 /* If we replace a MEM, make sure that we replace it for all
3017 occurrences of the same MEM in the insn. */
3018 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3019 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3021 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3022 if (op == 2
3023 && MEM_P (OP (op))
3024 && (REGNO (XEXP (OP (op), 0)) == SP_REG
3025 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3026 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3028 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3029 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3031 if (replace_in_op0)
3032 OP (0) = OP (op);
3033 if (replace_in_op1)
3034 OP (1) = OP (op);
3035 break;
3036 case 1:
3037 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3038 break;
3039 case 2:
3040 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3041 break;
3043 which ++;
3046 MUST_BE_OK (insn);
3049 /* Scan all insns and devirtualize them. */
3050 static void
3051 rl78_alloc_physical_registers (void)
3053 /* During most of the compile, gcc is dealing with virtual
3054 registers. At this point, we need to assign physical registers
3055 to the vitual ones, and copy in/out as needed. */
3057 rtx insn, curr;
3058 enum attr_valloc valloc_method;
3060 for (insn = get_insns (); insn; insn = curr)
3062 int i;
3064 curr = next_nonnote_nondebug_insn (insn);
3066 if (INSN_P (insn)
3067 && (GET_CODE (PATTERN (insn)) == SET
3068 || GET_CODE (PATTERN (insn)) == CALL)
3069 && INSN_CODE (insn) == -1)
3071 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3072 continue;
3073 i = recog (PATTERN (insn), insn, 0);
3074 if (i == -1)
3076 debug_rtx (insn);
3077 gcc_unreachable ();
3079 INSN_CODE (insn) = i;
3083 cfun->machine->virt_insns_ok = 0;
3084 cfun->machine->real_insns_ok = 1;
3086 clear_content_memory ();
3088 for (insn = get_insns (); insn; insn = curr)
3090 rtx pattern;
3092 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3094 if (!INSN_P (insn))
3096 if (LABEL_P (insn))
3097 clear_content_memory ();
3099 continue;
3102 if (dump_file)
3103 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3105 pattern = PATTERN (insn);
3106 if (GET_CODE (pattern) == PARALLEL)
3107 pattern = XVECEXP (pattern, 0, 0);
3108 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3109 clear_content_memory ();
3110 if (GET_CODE (pattern) != SET
3111 && GET_CODE (pattern) != CALL)
3112 continue;
3113 if (GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3114 continue;
3116 valloc_method = get_attr_valloc (insn);
3118 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3120 if (valloc_method == VALLOC_MACAX)
3122 record_content (AX, NULL_RTX);
3123 record_content (BC, NULL_RTX);
3124 record_content (DE, NULL_RTX);
3127 if (insn_ok_now (insn))
3128 continue;
3130 INSN_CODE (insn) = -1;
3132 if (RTX_FRAME_RELATED_P (insn))
3133 virt_insn_was_frame = 1;
3134 else
3135 virt_insn_was_frame = 0;
3137 switch (valloc_method)
3139 case VALLOC_OP1:
3140 rl78_alloc_physical_registers_op1 (insn);
3141 break;
3142 case VALLOC_OP2:
3143 rl78_alloc_physical_registers_op2 (insn);
3144 break;
3145 case VALLOC_RO1:
3146 rl78_alloc_physical_registers_ro1 (insn);
3147 break;
3148 case VALLOC_CMP:
3149 rl78_alloc_physical_registers_cmp (insn);
3150 break;
3151 case VALLOC_UMUL:
3152 rl78_alloc_physical_registers_umul (insn);
3153 break;
3154 case VALLOC_MACAX:
3155 /* Macro that clobbers AX. */
3156 rl78_alloc_address_registers_macax (insn);
3157 record_content (AX, NULL_RTX);
3158 record_content (BC, NULL_RTX);
3159 record_content (DE, NULL_RTX);
3160 break;
3163 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3164 clear_content_memory ();
3165 else
3166 process_postponed_content_update ();
3168 #if DEBUG_ALLOC
3169 fprintf (stderr, "\033[0m");
3170 #endif
3173 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3174 This function scans for uses of registers; the last use (i.e. first
3175 encounter when scanning backwards) triggers a REG_DEAD note if the
3176 reg was previously in DEAD[]. */
3177 static void
3178 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3180 const char *fmt;
3181 int i, r;
3182 enum rtx_code code;
3184 if (!s)
3185 return;
3187 code = GET_CODE (s);
3189 switch (code)
3191 /* Compare registers by number. */
3192 case REG:
3193 r = REGNO (s);
3194 if (dump_file)
3196 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3197 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3198 print_rtl_single (dump_file, s);
3200 if (dead [r])
3201 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3202 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3203 dead [r + i] = 0;
3204 return;
3206 /* These codes have no constituent expressions
3207 and are unique. */
3208 case SCRATCH:
3209 case CC0:
3210 case PC:
3211 return;
3213 case CONST_INT:
3214 case CONST_VECTOR:
3215 case CONST_DOUBLE:
3216 case CONST_FIXED:
3217 /* These are kept unique for a given value. */
3218 return;
3220 default:
3221 break;
3224 fmt = GET_RTX_FORMAT (code);
3226 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3228 if (fmt[i] == 'E')
3230 int j;
3231 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3232 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3234 else if (fmt[i] == 'e')
3235 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3239 /* Like the previous function, but scan for SETs instead. */
3240 static void
3241 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3243 int r, i;
3245 if (GET_CODE (d) != REG)
3246 return;
3248 r = REGNO (d);
3249 if (dead [r])
3250 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3251 if (dump_file)
3252 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3253 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3254 dead [r + i] = 1;
3257 /* This is a rather crude register death pass. Death status is reset
3258 at every jump or call insn. */
3259 static void
3260 rl78_calculate_death_notes (void)
3262 char dead[FIRST_PSEUDO_REGISTER];
3263 rtx insn, p, s, d;
3264 int i;
3266 memset (dead, 0, sizeof (dead));
3268 for (insn = get_last_insn ();
3269 insn;
3270 insn = prev_nonnote_nondebug_insn (insn))
3272 if (dump_file)
3274 fprintf (dump_file, "\n--------------------------------------------------");
3275 fprintf (dump_file, "\nDead:");
3276 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3277 if (dead[i])
3278 fprintf (dump_file, " %s", reg_names[i]);
3279 fprintf (dump_file, "\n");
3280 print_rtl_single (dump_file, insn);
3283 switch (GET_CODE (insn))
3285 case INSN:
3286 p = PATTERN (insn);
3287 switch (GET_CODE (p))
3289 case SET:
3290 s = SET_SRC (p);
3291 d = SET_DEST (p);
3292 rl78_note_reg_set (dead, d, insn);
3293 rl78_note_reg_uses (dead, s, insn);
3294 break;
3296 case USE:
3297 rl78_note_reg_uses (dead, p, insn);
3298 break;
3300 default:
3301 break;
3303 break;
3305 case JUMP_INSN:
3306 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3308 memset (dead, 1, sizeof (dead));
3309 /* We expect a USE just prior to this, which will mark
3310 the actual return registers. The USE will have a
3311 death note, but we aren't going to be modifying it
3312 after this pass. */
3313 break;
3315 case CALL_INSN:
3316 memset (dead, 0, sizeof (dead));
3317 break;
3319 default:
3320 break;
3322 if (dump_file)
3323 print_rtl_single (dump_file, insn);
3327 /* Helper function to reset the origins in RP and the age in AGE for
3328 all registers. */
3329 static void
3330 reset_origins (int *rp, int *age)
3332 int i;
3333 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3335 rp[i] = i;
3336 age[i] = 0;
3340 /* The idea behind this optimization is to look for cases where we
3341 move data from A to B to C, and instead move from A to B, and A to
3342 C. If B is a virtual register or memory, this is a big win on its
3343 own. If B turns out to be unneeded after this, it's a bigger win.
3344 For each register, we try to determine where it's value originally
3345 came from, if it's propogated purely through moves (and not
3346 computes). The ORIGINS[] array has the regno for the "origin" of
3347 the value in the [regno] it's indexed by. */
3348 static void
3349 rl78_propogate_register_origins (void)
3351 int origins[FIRST_PSEUDO_REGISTER];
3352 int age[FIRST_PSEUDO_REGISTER];
3353 int i;
3354 rtx insn, ninsn = NULL_RTX;
3355 rtx pat;
3357 reset_origins (origins, age);
3359 for (insn = get_insns (); insn; insn = ninsn)
3361 ninsn = next_nonnote_nondebug_insn (insn);
3363 if (dump_file)
3365 fprintf (dump_file, "\n");
3366 fprintf (dump_file, "Origins:");
3367 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3368 if (origins[i] != i)
3369 fprintf (dump_file, " r%d=r%d", i, origins[i]);
3370 fprintf (dump_file, "\n");
3371 print_rtl_single (dump_file, insn);
3374 switch (GET_CODE (insn))
3376 case CODE_LABEL:
3377 case BARRIER:
3378 case CALL_INSN:
3379 case JUMP_INSN:
3380 reset_origins (origins, age);
3381 break;
3383 default:
3384 break;
3386 case INSN:
3387 pat = PATTERN (insn);
3389 if (GET_CODE (pat) == PARALLEL)
3391 rtx clobber = XVECEXP (pat, 0, 1);
3392 pat = XVECEXP (pat, 0, 0);
3393 if (GET_CODE (clobber) == CLOBBER)
3395 int cr = REGNO (XEXP (clobber, 0));
3396 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3397 if (dump_file)
3398 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3399 for (i = 0; i < mb; i++)
3401 origins[cr + i] = cr + i;
3402 age[cr + i] = 0;
3405 else
3406 break;
3409 if (GET_CODE (pat) == SET)
3411 rtx src = SET_SRC (pat);
3412 rtx dest = SET_DEST (pat);
3413 int mb = GET_MODE_SIZE (GET_MODE (dest));
3415 if (GET_CODE (dest) == REG)
3417 int dr = REGNO (dest);
3419 if (GET_CODE (src) == REG)
3421 int sr = REGNO (src);
3422 int same = 1;
3423 int best_age, best_reg;
3425 /* See if the copy is not needed. */
3426 for (i = 0; i < mb; i ++)
3427 if (origins[dr + i] != origins[sr + i])
3428 same = 0;
3429 if (same)
3431 if (dump_file)
3432 fprintf (dump_file, "deleting because dest already has correct value\n");
3433 delete_insn (insn);
3434 break;
3437 if (dr < 8 || sr >= 8)
3439 int ar;
3441 best_age = -1;
3442 best_reg = -1;
3443 /* See if the copy can be made from another
3444 bank 0 register instead, instead of the
3445 virtual src register. */
3446 for (ar = 0; ar < 8; ar += mb)
3448 same = 1;
3449 for (i = 0; i < mb; i ++)
3450 if (origins[ar + i] != origins[sr + i])
3451 same = 0;
3453 /* The chip has some reg-reg move limitations. */
3454 if (mb == 1 && dr > 3)
3455 same = 0;
3457 if (same)
3459 if (best_age == -1 || best_age > age[sr + i])
3461 best_age = age[sr + i];
3462 best_reg = sr;
3467 if (best_reg != -1)
3469 /* FIXME: copy debug info too. */
3470 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3471 sr = best_reg;
3475 for (i = 0; i < mb; i++)
3477 origins[dr + i] = origins[sr + i];
3478 age[dr + i] = age[sr + i] + 1;
3481 else
3483 /* The destination is computed, its origin is itself. */
3484 if (dump_file)
3485 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3486 dr, mb, mb == 1 ? "" : "s");
3487 for (i = 0; i < mb; i ++)
3489 origins[dr + i] = dr + i;
3490 age[dr + i] = 0;
3494 /* Any registers marked with that reg as an origin are reset. */
3495 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3496 if (origins[i] >= dr && origins[i] < dr + mb)
3498 origins[i] = i;
3499 age[i] = 0;
3503 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3504 if (get_attr_valloc (insn) == VALLOC_MACAX)
3506 if (dump_file)
3507 fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
3508 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3509 if (i <= 3 || origins[i] <= 3)
3511 origins[i] = i;
3512 age[i] = 0;
3516 if (GET_CODE (src) == ASHIFT
3517 || GET_CODE (src) == ASHIFTRT
3518 || GET_CODE (src) == LSHIFTRT)
3520 rtx count = XEXP (src, 1);
3521 if (GET_CODE (count) == REG)
3523 /* Special case - our pattern clobbers the count register. */
3524 int r = REGNO (count);
3525 if (dump_file)
3526 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3527 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3528 if (i == r || origins[i] == r)
3530 origins[i] = i;
3531 age[i] = 0;
3540 /* Remove any SETs where the destination is unneeded. */
3541 static void
3542 rl78_remove_unused_sets (void)
3544 rtx insn, ninsn = NULL_RTX;
3545 rtx dest;
3547 for (insn = get_insns (); insn; insn = ninsn)
3549 ninsn = next_nonnote_nondebug_insn (insn);
3551 if ((insn = single_set (insn)) == NULL_RTX)
3552 continue;
3554 dest = SET_DEST (insn);
3556 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3557 continue;
3559 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3560 delete_insn (insn);
3564 /* This is the top of the devritualization pass. */
3565 static void
3566 rl78_reorg (void)
3568 /* split2 only happens when optimizing, but we need all movSIs to be
3569 split now. */
3570 if (optimize <= 0)
3571 split_all_insns ();
3573 rl78_alloc_physical_registers ();
3575 if (dump_file)
3577 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3578 print_rtl_with_bb (dump_file, get_insns (), 0);
3581 rl78_propogate_register_origins ();
3582 rl78_calculate_death_notes ();
3584 if (dump_file)
3586 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3587 print_rtl_with_bb (dump_file, get_insns (), 0);
3588 fprintf (dump_file, "\n======================================================================\n");
3591 rl78_remove_unused_sets ();
3593 /* The code after devirtualizing has changed so much that at this point
3594 we might as well just rescan everything. Note that
3595 df_rescan_all_insns is not going to help here because it does not
3596 touch the artificial uses and defs. */
3597 df_finish_pass (true);
3598 if (optimize > 1)
3599 df_live_add_problem ();
3600 df_scan_alloc (NULL);
3601 df_scan_blocks ();
3603 if (optimize)
3604 df_analyze ();
3607 #undef TARGET_RETURN_IN_MEMORY
3608 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3610 static bool
3611 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3613 const HOST_WIDE_INT size = int_size_in_bytes (type);
3614 return (size == -1 || size > 8);
3618 #undef TARGET_RTX_COSTS
3619 #define TARGET_RTX_COSTS rl78_rtx_costs
3621 static bool rl78_rtx_costs (rtx x,
3622 int code,
3623 int outer_code ATTRIBUTE_UNUSED,
3624 int opno ATTRIBUTE_UNUSED,
3625 int * total,
3626 bool speed ATTRIBUTE_UNUSED)
3628 if (code == IF_THEN_ELSE)
3629 return COSTS_N_INSNS (10);
3630 if (GET_MODE (x) == SImode)
3632 switch (code)
3634 case MULT:
3635 if (RL78_MUL_RL78)
3636 *total = COSTS_N_INSNS (14);
3637 else if (RL78_MUL_G13)
3638 *total = COSTS_N_INSNS (29);
3639 else
3640 *total = COSTS_N_INSNS (500);
3641 return true;
3642 case PLUS:
3643 *total = COSTS_N_INSNS (8);
3644 return true;
3645 case ASHIFT:
3646 case ASHIFTRT:
3647 case LSHIFTRT:
3648 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3650 switch (INTVAL (XEXP (x, 1)))
3652 case 0: *total = COSTS_N_INSNS (0); break;
3653 case 1: *total = COSTS_N_INSNS (6); break;
3654 case 2: case 3: case 4: case 5: case 6: case 7:
3655 *total = COSTS_N_INSNS (10); break;
3656 case 8: *total = COSTS_N_INSNS (6); break;
3657 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3658 *total = COSTS_N_INSNS (10); break;
3659 case 16: *total = COSTS_N_INSNS (3); break;
3660 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3661 *total = COSTS_N_INSNS (4); break;
3662 case 24: *total = COSTS_N_INSNS (4); break;
3663 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3664 *total = COSTS_N_INSNS (5); break;
3667 else
3668 *total = COSTS_N_INSNS (10+4*16);
3669 return true;
3672 return false;
3676 #undef TARGET_UNWIND_WORD_MODE
3677 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3679 static enum machine_mode
3680 rl78_unwind_word_mode (void)
3682 return HImode;
3685 struct gcc_target targetm = TARGET_INITIALIZER;
3687 #include "gt-rl78.h"