rl78.c: Various whitespace and comment tweaks.
[official-gcc.git] / gcc / config / rl78 / rl78.c
blobfb987b2eae9bdbcdc291a5f9856b4f8432d5ade5
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 /* Redundant move elimination pass. Must be run after the basic block
174 reordering pass for the best effect. */
176 static unsigned int
177 move_elim_pass (void)
179 rtx insn, ninsn, prev = NULL_RTX;
181 for (insn = get_insns (); insn; insn = ninsn)
183 rtx set;
185 ninsn = next_nonnote_nondebug_insn (insn);
187 if ((set = single_set (insn)) == NULL_RTX)
189 prev = NULL_RTX;
190 continue;
193 /* If we have two SET insns in a row (without anything
194 between them) and the source of the second one is the
195 destination of the first one, and vice versa, then we
196 can eliminate the second SET. */
197 if (prev
198 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
199 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
202 if (dump_file)
203 fprintf (dump_file, " Delete insn %d because it is redundant\n",
204 INSN_UID (insn));
206 delete_insn (insn);
207 prev = NULL_RTX;
209 else
210 prev = set;
213 if (dump_file)
214 print_rtl_with_bb (dump_file, get_insns (), 0);
216 return 0;
219 namespace {
221 const pass_data pass_data_rl78_move_elim =
223 RTL_PASS, /* type */
224 "move_elim", /* name */
225 OPTGROUP_NONE, /* optinfo_flags */
226 true, /* has_gate */
227 true, /* has_execute */
228 TV_MACH_DEP, /* tv_id */
229 0, /* properties_required */
230 0, /* properties_provided */
231 0, /* properties_destroyed */
232 0, /* todo_flags_start */
233 0, /* todo_flags_finish */
236 class pass_rl78_move_elim : public rtl_opt_pass
238 public:
239 pass_rl78_move_elim(gcc::context *ctxt)
240 : rtl_opt_pass(pass_data_rl78_move_elim, ctxt)
244 /* opt_pass methods: */
245 bool gate () { return devirt_gate (); }
246 unsigned int execute () { return move_elim_pass (); }
249 } // anon namespace
251 rtl_opt_pass *
252 make_pass_rl78_move_elim (gcc::context *ctxt)
254 return new pass_rl78_move_elim (ctxt);
257 #undef TARGET_ASM_FILE_START
258 #define TARGET_ASM_FILE_START rl78_asm_file_start
260 static void
261 rl78_asm_file_start (void)
263 int i;
265 if (TARGET_G10)
267 /* The memory used is 0xffec8 to 0xffedf; real registers are in
268 0xffee0 to 0xffee7. */
269 for (i = 8; i < 32; i++)
270 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
272 else
274 for (i = 0; i < 8; i++)
276 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
277 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
278 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
282 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
283 static struct register_pass_info rl78_devirt_info =
285 rl78_devirt_pass,
286 "pro_and_epilogue",
288 PASS_POS_INSERT_BEFORE
291 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
292 static struct register_pass_info rl78_move_elim_info =
294 rl78_move_elim_pass,
295 "bbro",
297 PASS_POS_INSERT_AFTER
300 register_pass (& rl78_devirt_info);
301 register_pass (& rl78_move_elim_info);
305 #undef TARGET_OPTION_OVERRIDE
306 #define TARGET_OPTION_OVERRIDE rl78_option_override
308 static void
309 rl78_option_override (void)
311 flag_omit_frame_pointer = 1;
312 flag_no_function_cse = 1;
313 flag_split_wide_types = 0;
315 init_machine_status = rl78_init_machine_status;
317 if (TARGET_ALLREGS)
319 int i;
321 for (i = 24; i < 32; i++)
322 fixed_regs[i] = 0;
326 /* Most registers are 8 bits. Some are 16 bits because, for example,
327 gcc doesn't like dealing with $FP as a register pair. This table
328 maps register numbers to size in bytes. */
329 static const int register_sizes[] =
331 1, 1, 1, 1, 1, 1, 1, 1,
332 1, 1, 1, 1, 1, 1, 1, 1,
333 1, 1, 1, 1, 1, 1, 2, 1,
334 1, 1, 1, 1, 1, 1, 1, 1,
335 2, 2, 1, 1, 1
338 /* Predicates used in the MD patterns. This one is true when virtual
339 insns may be matched, which typically means before (or during) the
340 devirt pass. */
341 bool
342 rl78_virt_insns_ok (void)
344 if (cfun)
345 return cfun->machine->virt_insns_ok;
346 return true;
349 /* Predicates used in the MD patterns. This one is true when real
350 insns may be matched, which typically means after (or during) the
351 devirt pass. */
352 bool
353 rl78_real_insns_ok (void)
355 if (cfun)
356 return cfun->machine->real_insns_ok;
357 return false;
360 /* Implements HARD_REGNO_NREGS. */
362 rl78_hard_regno_nregs (int regno, enum machine_mode mode)
364 int rs = register_sizes[regno];
365 if (rs < 1)
366 rs = 1;
367 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
370 /* Implements HARD_REGNO_MODE_OK. */
372 rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
374 int s = GET_MODE_SIZE (mode);
376 if (s < 1)
377 return 0;
378 /* These are not to be used by gcc. */
379 if (regno == 23 || regno == ES_REG || regno == CS_REG)
380 return 0;
381 /* $fp can alway sbe accessed as a 16-bit value. */
382 if (regno == FP_REG && s == 2)
383 return 1;
384 if (regno < SP_REG)
386 /* Since a reg-reg move is really a reg-mem move, we must
387 enforce alignment. */
388 if (s > 1 && (regno % 2))
389 return 0;
390 return 1;
392 if (s == CC_REGNUM)
393 return (mode == BImode);
394 /* All other registers must be accessed in their natural sizes. */
395 if (s == register_sizes [regno])
396 return 1;
397 return 0;
400 /* Simplify_gen_subreg() doesn't handle memory references the way we
401 need it to below, so we use this function for when we must get a
402 valid subreg in a "natural" state. */
403 static rtx
404 rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
406 if (GET_CODE (r) == MEM)
407 return adjust_address (r, mode, byte);
408 else
409 return simplify_gen_subreg (mode, r, omode, byte);
412 /* Used by movsi. Split SImode moves into two HImode moves, using
413 appropriate patterns for the upper and lower halves of symbols. */
414 void
415 rl78_expand_movsi (rtx *operands)
417 rtx op00, op02, op10, op12;
419 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
420 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
421 if (GET_CODE (operands[1]) == CONST
422 || GET_CODE (operands[1]) == SYMBOL_REF)
424 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
425 op10 = gen_rtx_CONST (HImode, op10);
426 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
427 op12 = gen_rtx_CONST (HImode, op12);
429 else
431 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
432 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
435 if (rtx_equal_p (operands[0], operands[1]))
437 else if (rtx_equal_p (op00, op12))
439 emit_move_insn (op02, op12);
440 emit_move_insn (op00, op10);
442 else
444 emit_move_insn (op00, op10);
445 emit_move_insn (op02, op12);
449 /* Generate code to move an SImode value. */
450 void
451 rl78_split_movsi (rtx *operands)
453 rtx op00, op02, op10, op12;
455 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
456 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
458 if (GET_CODE (operands[1]) == CONST
459 || GET_CODE (operands[1]) == SYMBOL_REF)
461 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
462 op10 = gen_rtx_CONST (HImode, op10);
463 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
464 op12 = gen_rtx_CONST (HImode, op12);
466 else
468 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
469 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
472 if (rtx_equal_p (operands[0], operands[1]))
474 else if (rtx_equal_p (op00, op12))
476 operands[2] = op02;
477 operands[4] = op12;
478 operands[3] = op00;
479 operands[5] = op10;
481 else
483 operands[2] = op00;
484 operands[4] = op10;
485 operands[3] = op02;
486 operands[5] = op12;
490 /* Used by various two-operand expanders which cannot accept all
491 operands in the "far" namespace. Force some such operands into
492 registers so that each pattern has at most one far operand. */
494 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
496 int did = 0;
497 rtx temp_reg = NULL;
499 /* FIXME: in the future, be smarter about only doing this if the
500 other operand is also far, assuming the devirtualizer can also
501 handle that. */
502 if (rl78_far_p (operands[0]))
504 temp_reg = operands[0];
505 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
506 did = 1;
508 if (!did)
509 return 0;
511 emit_insn (gen (operands[0], operands[1]));
512 if (temp_reg)
513 emit_move_insn (temp_reg, operands[0]);
514 return 1;
517 /* Likewise, but for three-operand expanders. */
519 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
521 int did = 0;
522 rtx temp_reg = NULL;
524 /* FIXME: Likewise. */
525 if (rl78_far_p (operands[1]))
527 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
528 emit_move_insn (temp_reg, operands[1]);
529 operands[1] = temp_reg;
530 did = 1;
532 if (rl78_far_p (operands[0]))
534 temp_reg = operands[0];
535 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
536 did = 1;
538 if (!did)
539 return 0;
541 emit_insn (gen (operands[0], operands[1], operands[2]));
542 if (temp_reg)
543 emit_move_insn (temp_reg, operands[0]);
544 return 1;
547 #undef TARGET_CAN_ELIMINATE
548 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
550 static bool
551 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
553 return true;
556 /* Returns true if the given register needs to be saved by the
557 current function. */
558 static bool
559 need_to_save (unsigned int regno)
561 if (is_interrupt_func (cfun->decl))
563 /* We don't know what devirt will need */
564 if (regno < 8)
565 return true;
567 /* We don't need to save registers that have
568 been reserved for interrupt handlers. */
569 if (regno > 23)
570 return false;
572 /* If the handler is a non-leaf function then it may call
573 non-interrupt aware routines which will happily clobber
574 any call_used registers, so we have to preserve them. */
575 if (!crtl->is_leaf && call_used_regs[regno])
576 return true;
578 /* Otherwise we only have to save a register, call_used
579 or not, if it is used by this handler. */
580 return df_regs_ever_live_p (regno);
583 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
584 return true;
585 if (fixed_regs[regno])
586 return false;
587 if (crtl->calls_eh_return)
588 return true;
589 if (df_regs_ever_live_p (regno)
590 && !call_used_regs[regno])
591 return true;
592 return false;
595 /* We use this to wrap all emitted insns in the prologue. */
596 static rtx
597 F (rtx x)
599 RTX_FRAME_RELATED_P (x) = 1;
600 return x;
603 /* Compute all the frame-related fields in our machine_function
604 structure. */
605 static void
606 rl78_compute_frame_info (void)
608 int i;
610 cfun->machine->computed = 1;
611 cfun->machine->framesize_regs = 0;
612 cfun->machine->framesize_locals = get_frame_size ();
613 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
615 for (i = 0; i < 16; i ++)
616 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
618 cfun->machine->need_to_push [i] = 1;
619 cfun->machine->framesize_regs += 2;
621 else
622 cfun->machine->need_to_push [i] = 0;
624 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
625 cfun->machine->framesize_locals ++;
627 cfun->machine->framesize = (cfun->machine->framesize_regs
628 + cfun->machine->framesize_locals
629 + cfun->machine->framesize_outgoing);
632 /* Returns true if the provided function has the specified attribute. */
633 static inline bool
634 has_func_attr (const_tree decl, const char * func_attr)
636 if (decl == NULL_TREE)
637 decl = current_function_decl;
639 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
642 /* Returns true if the provided function has the "interrupt" attribute. */
643 static inline bool
644 is_interrupt_func (const_tree decl)
646 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
649 /* Returns true if the provided function has the "brk_interrupt" attribute. */
650 static inline bool
651 is_brk_interrupt_func (const_tree decl)
653 return has_func_attr (decl, "brk_interrupt");
656 /* Check "interrupt" attributes. */
657 static tree
658 rl78_handle_func_attribute (tree * node,
659 tree name,
660 tree args,
661 int flags ATTRIBUTE_UNUSED,
662 bool * no_add_attrs)
664 gcc_assert (DECL_P (* node));
665 gcc_assert (args == NULL_TREE);
667 if (TREE_CODE (* node) != FUNCTION_DECL)
669 warning (OPT_Wattributes, "%qE attribute only applies to functions",
670 name);
671 * no_add_attrs = true;
674 /* FIXME: We ought to check that the interrupt and exception
675 handler attributes have been applied to void functions. */
676 return NULL_TREE;
679 #undef TARGET_ATTRIBUTE_TABLE
680 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
682 /* Table of RL78-specific attributes. */
683 const struct attribute_spec rl78_attribute_table[] =
685 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
686 affects_type_identity. */
687 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
688 false },
689 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
690 false },
691 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute,
692 false },
693 { NULL, 0, 0, false, false, false, NULL, false }
698 /* Break down an address RTX into its component base/index/addend
699 portions and return TRUE if the address is of a valid form, else
700 FALSE. */
701 static bool
702 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
704 *base = NULL_RTX;
705 *index = NULL_RTX;
706 *addend = NULL_RTX;
708 if (GET_CODE (x) == UNSPEC
709 && XINT (x, 1) == UNS_ES_ADDR)
710 x = XVECEXP (x, 0, 1);
712 if (GET_CODE (x) == REG)
714 *base = x;
715 return true;
718 /* We sometimes get these without the CONST wrapper */
719 if (GET_CODE (x) == PLUS
720 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
721 && GET_CODE (XEXP (x, 1)) == CONST_INT)
723 *addend = x;
724 return true;
727 if (GET_CODE (x) == PLUS)
729 *base = XEXP (x, 0);
730 x = XEXP (x, 1);
732 if (GET_CODE (*base) != REG
733 && GET_CODE (x) == REG)
735 rtx tmp = *base;
736 *base = x;
737 x = tmp;
740 if (GET_CODE (*base) != REG)
741 return false;
743 if (GET_CODE (x) == ZERO_EXTEND
744 && GET_CODE (XEXP (x, 0)) == REG)
746 *index = XEXP (x, 0);
747 return false;
751 switch (GET_CODE (x))
753 case PLUS:
754 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
755 && GET_CODE (XEXP (x, 0)) == CONST_INT)
757 *addend = x;
758 return true;
760 /* fall through */
761 case MEM:
762 case REG:
763 return false;
765 case CONST:
766 case SYMBOL_REF:
767 case CONST_INT:
768 *addend = x;
769 return true;
771 default:
772 return false;
775 return false;
778 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
779 addressing. */
780 bool
781 rl78_hl_b_c_addr_p (rtx op)
783 rtx hl, bc;
785 if (GET_CODE (op) != PLUS)
786 return false;
787 hl = XEXP (op, 0);
788 bc = XEXP (op, 1);
789 if (GET_CODE (hl) == ZERO_EXTEND)
791 rtx tmp = hl;
792 hl = bc;
793 bc = tmp;
795 if (GET_CODE (hl) != REG)
796 return false;
797 if (GET_CODE (bc) != ZERO_EXTEND)
798 return false;
799 bc = XEXP (bc, 0);
800 if (GET_CODE (bc) != REG)
801 return false;
802 if (REGNO (hl) != HL_REG)
803 return false;
804 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
805 return false;
807 return true;
810 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
812 /* Used in various constraints and predicates to match operands in the
813 "far" address space. */
815 rl78_far_p (rtx x)
817 if (! MEM_P (x))
818 return 0;
819 #if DEBUG0
820 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
821 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
822 #endif
823 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
826 /* Return the appropriate mode for a named address pointer. */
827 #undef TARGET_ADDR_SPACE_POINTER_MODE
828 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
829 static enum machine_mode
830 rl78_addr_space_pointer_mode (addr_space_t addrspace)
832 switch (addrspace)
834 case ADDR_SPACE_GENERIC:
835 return HImode;
836 case ADDR_SPACE_FAR:
837 return SImode;
838 default:
839 gcc_unreachable ();
843 /* Returns TRUE for valid addresses. */
844 #undef TARGET_VALID_POINTER_MODE
845 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
846 static bool
847 rl78_valid_pointer_mode (enum machine_mode m)
849 return (m == HImode || m == SImode);
852 /* Return the appropriate mode for a named address address. */
853 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
854 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
855 static enum machine_mode
856 rl78_addr_space_address_mode (addr_space_t addrspace)
858 switch (addrspace)
860 case ADDR_SPACE_GENERIC:
861 return HImode;
862 case ADDR_SPACE_FAR:
863 return SImode;
864 default:
865 gcc_unreachable ();
869 #undef TARGET_LEGITIMATE_CONSTANT_P
870 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
872 static bool
873 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
875 return true;
878 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
879 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
881 bool
882 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
883 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
885 rtx base, index, addend;
886 bool is_far_addr = false;
888 if (GET_CODE (x) == UNSPEC
889 && XINT (x, 1) == UNS_ES_ADDR)
891 x = XVECEXP (x, 0, 1);
892 is_far_addr = true;
895 if (as == ADDR_SPACE_GENERIC
896 && (GET_MODE (x) == SImode || is_far_addr))
897 return false;
899 if (! characterize_address (x, &base, &index, &addend))
900 return false;
902 /* We can't extract the high/low portions of a PLUS address
903 involving a register during devirtualization, so make sure all
904 such __far addresses do not have addends. This forces GCC to do
905 the sum separately. */
906 if (addend && base && as == ADDR_SPACE_FAR)
907 return false;
909 if (base && index)
911 int ir = REGNO (index);
912 int br = REGNO (base);
914 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
915 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
916 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
917 return false;
920 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
921 return false;
923 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
924 && REGNO (base) >= 8 && REGNO (base) <= 31)
925 return false;
927 return true;
930 /* Determine if one named address space is a subset of another. */
931 #undef TARGET_ADDR_SPACE_SUBSET_P
932 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
933 static bool
934 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
936 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
937 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
939 if (subset == superset)
940 return true;
942 else
943 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
946 #undef TARGET_ADDR_SPACE_CONVERT
947 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
948 /* Convert from one address space to another. */
949 static rtx
950 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
952 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
953 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
954 rtx result;
956 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
957 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
959 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
961 /* This is unpredictable, as we're truncating off usable address
962 bits. */
964 result = gen_reg_rtx (HImode);
965 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
966 return result;
968 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
970 /* This always works. */
971 result = gen_reg_rtx (SImode);
972 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
973 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
974 return result;
976 else
977 gcc_unreachable ();
980 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
981 bool
982 rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
983 addr_space_t address_space ATTRIBUTE_UNUSED,
984 int outer_code ATTRIBUTE_UNUSED, int index_code)
986 if (regno <= SP_REG && regno >= 16)
987 return true;
988 if (index_code == REG)
989 return (regno == HL_REG);
990 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
991 return true;
992 return false;
995 /* Implements MODE_CODE_BASE_REG_CLASS. */
996 enum reg_class
997 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
998 addr_space_t address_space ATTRIBUTE_UNUSED,
999 int outer_code ATTRIBUTE_UNUSED,
1000 int index_code ATTRIBUTE_UNUSED)
1002 return V_REGS;
1005 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1006 described in the machine_Function struct definition, above. */
1008 rl78_initial_elimination_offset (int from, int to)
1010 int rv = 0; /* as if arg to arg */
1012 rl78_compute_frame_info ();
1014 switch (to)
1016 case STACK_POINTER_REGNUM:
1017 rv += cfun->machine->framesize_outgoing;
1018 rv += cfun->machine->framesize_locals;
1019 /* Fall through. */
1020 case FRAME_POINTER_REGNUM:
1021 rv += cfun->machine->framesize_regs;
1022 rv += 4;
1023 break;
1024 default:
1025 gcc_unreachable ();
1028 switch (from)
1030 case FRAME_POINTER_REGNUM:
1031 rv -= 4;
1032 rv -= cfun->machine->framesize_regs;
1033 case ARG_POINTER_REGNUM:
1034 break;
1035 default:
1036 gcc_unreachable ();
1039 return rv;
1042 static int
1043 rl78_is_naked_func (void)
1045 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1048 /* Expand the function prologue (from the prologue pattern). */
1049 void
1050 rl78_expand_prologue (void)
1052 int i, fs;
1053 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1054 int rb = 0;
1056 if (rl78_is_naked_func ())
1057 return;
1059 /* Always re-compute the frame info - the register usage may have changed. */
1060 rl78_compute_frame_info ();
1062 if (flag_stack_usage_info)
1063 current_function_static_stack_size = cfun->machine->framesize;
1065 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1066 for (i = 0; i < 4; i++)
1067 if (cfun->machine->need_to_push [i])
1069 /* Select Bank 0 if we are using any registers from Bank 0. */
1070 emit_insn (gen_sel_rb (GEN_INT (0)));
1071 break;
1074 for (i = 0; i < 16; i++)
1075 if (cfun->machine->need_to_push [i])
1077 if (TARGET_G10)
1079 emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
1080 F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
1082 else
1084 int need_bank = i/4;
1086 if (need_bank != rb)
1088 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1089 rb = need_bank;
1091 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
1095 if (rb != 0)
1096 emit_insn (gen_sel_rb (GEN_INT (0)));
1098 if (frame_pointer_needed)
1100 F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1101 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
1102 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
1103 gen_rtx_REG (HImode, AX_REG)));
1106 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1107 while (fs > 0)
1109 int fs_byte = (fs > 254) ? 254 : fs;
1110 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1111 fs -= fs_byte;
1115 /* Expand the function epilogue (from the epilogue pattern). */
1116 void
1117 rl78_expand_epilogue (void)
1119 int i, fs;
1120 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1121 int rb = 0;
1123 if (rl78_is_naked_func ())
1124 return;
1126 if (frame_pointer_needed)
1128 emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1129 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1130 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
1131 gen_rtx_REG (HImode, AX_REG));
1133 else
1135 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1136 while (fs > 0)
1138 int fs_byte = (fs > 254) ? 254 : fs;
1140 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1141 fs -= fs_byte;
1145 for (i = 15; i >= 0; i--)
1146 if (cfun->machine->need_to_push [i])
1148 if (TARGET_G10)
1150 emit_insn (gen_pop (gen_rtx_REG (HImode, 0)));
1151 emit_move_insn (gen_rtx_REG (HImode, i*2), gen_rtx_REG (HImode, 0));
1153 else
1155 int need_bank = i / 4;
1157 if (need_bank != rb)
1159 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1160 rb = need_bank;
1162 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
1166 if (rb != 0)
1167 emit_insn (gen_sel_rb (GEN_INT (0)));
1169 if (cfun->machine->trampolines_used)
1170 emit_insn (gen_trampoline_uninit ());
1172 if (is_brk_interrupt_func (cfun->decl))
1173 emit_jump_insn (gen_brk_interrupt_return ());
1174 else if (is_interrupt_func (cfun->decl))
1175 emit_jump_insn (gen_interrupt_return ());
1176 else
1177 emit_jump_insn (gen_rl78_return ());
1180 /* Likewise, for exception handlers. */
1181 void
1182 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1184 /* FIXME - replace this with an indirect jump with stack adjust. */
1185 emit_jump_insn (gen_rl78_return ());
1188 #undef TARGET_ASM_FUNCTION_PROLOGUE
1189 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1191 /* We don't use this to actually emit the function prologue. We use
1192 this to insert a comment in the asm file describing the
1193 function. */
1194 static void
1195 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1197 int i;
1199 if (cfun->machine->framesize == 0)
1200 return;
1201 fprintf (file, "\t; start of function\n");
1203 if (cfun->machine->framesize_regs)
1205 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1206 for (i = 0; i < 16; i ++)
1207 if (cfun->machine->need_to_push[i])
1208 fprintf (file, " %s", word_regnames[i*2]);
1209 fprintf (file, "\n");
1212 if (frame_pointer_needed)
1213 fprintf (file, "\t; $fp points here (r22)\n");
1215 if (cfun->machine->framesize_locals)
1216 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1217 cfun->machine->framesize_locals == 1 ? "" : "s");
1219 if (cfun->machine->framesize_outgoing)
1220 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1221 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1224 /* Return an RTL describing where a function return value of type RET_TYPE
1225 is held. */
1227 #undef TARGET_FUNCTION_VALUE
1228 #define TARGET_FUNCTION_VALUE rl78_function_value
1230 static rtx
1231 rl78_function_value (const_tree ret_type,
1232 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1233 bool outgoing ATTRIBUTE_UNUSED)
1235 enum machine_mode mode = TYPE_MODE (ret_type);
1237 return gen_rtx_REG (mode, 8);
1240 #undef TARGET_PROMOTE_FUNCTION_MODE
1241 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1243 static enum machine_mode
1244 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1245 enum machine_mode mode,
1246 int *punsignedp ATTRIBUTE_UNUSED,
1247 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1249 return mode;
1252 /* Return an RTL expression describing the register holding a function
1253 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1254 be passed on the stack. CUM describes the previous parameters to the
1255 function and NAMED is false if the parameter is part of a variable
1256 parameter list, or the last named parameter before the start of a
1257 variable parameter list. */
1259 #undef TARGET_FUNCTION_ARG
1260 #define TARGET_FUNCTION_ARG rl78_function_arg
1262 static rtx
1263 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1264 enum machine_mode mode ATTRIBUTE_UNUSED,
1265 const_tree type ATTRIBUTE_UNUSED,
1266 bool named ATTRIBUTE_UNUSED)
1268 return NULL_RTX;
1271 #undef TARGET_FUNCTION_ARG_ADVANCE
1272 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1274 static void
1275 rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1276 bool named ATTRIBUTE_UNUSED)
1278 int rounded_size;
1279 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1281 rounded_size = ((mode == BLKmode)
1282 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1283 if (rounded_size & 1)
1284 rounded_size ++;
1285 (*cum) += rounded_size;
1288 #undef TARGET_FUNCTION_ARG_BOUNDARY
1289 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1291 static unsigned int
1292 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1293 const_tree type ATTRIBUTE_UNUSED)
1295 return 16;
1298 /* Supported modifier letters:
1300 A - address of a MEM
1301 S - SADDR form of a real register
1302 v - real register corresponding to a virtual register
1303 m - minus - negative of CONST_INT value.
1304 c - inverse of a conditional (NE vs EQ for example)
1305 z - collapsed conditional
1306 s - shift count mod 8
1307 S - shift count mod 16
1308 r - reverse shift count (8-(count mod 8))
1309 B - bit position
1311 h - bottom HI of an SI
1312 H - top HI of an SI
1313 q - bottom QI of an HI
1314 Q - top QI of an HI
1315 e - third QI of an SI (i.e. where the ES register gets values from)
1316 E - fourth QI of an SI (i.e. MSB)
1320 /* Implements the bulk of rl78_print_operand, below. We do it this
1321 way because we need to test for a constant at the top level and
1322 insert the '#', but not test for it anywhere else as we recurse
1323 down into the operand. */
1324 static void
1325 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1327 int need_paren;
1329 switch (GET_CODE (op))
1331 case MEM:
1332 if (letter == 'A')
1333 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1334 else
1336 if (rl78_far_p (op))
1338 fprintf (file, "es:");
1339 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1341 if (letter == 'H')
1343 op = adjust_address (op, HImode, 2);
1344 letter = 0;
1346 if (letter == 'h')
1348 op = adjust_address (op, HImode, 0);
1349 letter = 0;
1351 if (letter == 'Q')
1353 op = adjust_address (op, QImode, 1);
1354 letter = 0;
1356 if (letter == 'q')
1358 op = adjust_address (op, QImode, 0);
1359 letter = 0;
1361 if (letter == 'e')
1363 op = adjust_address (op, QImode, 2);
1364 letter = 0;
1366 if (letter == 'E')
1368 op = adjust_address (op, QImode, 3);
1369 letter = 0;
1371 if (CONSTANT_P (XEXP (op, 0)))
1373 fprintf (file, "!");
1374 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1376 else if (GET_CODE (XEXP (op, 0)) == PLUS
1377 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1379 fprintf (file, "!");
1380 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1382 else if (GET_CODE (XEXP (op, 0)) == PLUS
1383 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1384 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1386 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1387 fprintf (file, "[");
1388 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1389 fprintf (file, "]");
1391 else
1393 fprintf (file, "[");
1394 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1395 fprintf (file, "]");
1398 break;
1400 case REG:
1401 if (letter == 'Q')
1402 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1403 else if (letter == 'H')
1404 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1405 else if (letter == 'q')
1406 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1407 else if (letter == 'e')
1408 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1409 else if (letter == 'E')
1410 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1411 else if (letter == 'S')
1412 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1413 else if (GET_MODE (op) == HImode
1414 && ! (REGNO (op) & ~0xfe))
1416 if (letter == 'v')
1417 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1418 else
1419 fprintf (file, "%s", word_regnames [REGNO (op)]);
1421 else
1422 fprintf (file, "%s", reg_names [REGNO (op)]);
1423 break;
1425 case CONST_INT:
1426 if (letter == 'Q')
1427 fprintf (file, "%ld", INTVAL (op) >> 8);
1428 else if (letter == 'H')
1429 fprintf (file, "%ld", INTVAL (op) >> 16);
1430 else if (letter == 'q')
1431 fprintf (file, "%ld", INTVAL (op) & 0xff);
1432 else if (letter == 'h')
1433 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1434 else if (letter == 'e')
1435 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1436 else if (letter == 'B')
1437 fprintf (file, "%d", exact_log2 (INTVAL (op)));
1438 else if (letter == 'E')
1439 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1440 else if (letter == 'm')
1441 fprintf (file, "%ld", - INTVAL (op));
1442 else if (letter == 's')
1443 fprintf (file, "%ld", INTVAL (op) % 8);
1444 else if (letter == 'S')
1445 fprintf (file, "%ld", INTVAL (op) % 16);
1446 else if (letter == 'r')
1447 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1448 else if (letter == 'C')
1449 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1450 else
1451 fprintf (file, "%ld", INTVAL (op));
1452 break;
1454 case CONST:
1455 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1456 break;
1458 case ZERO_EXTRACT:
1460 int bits = INTVAL (XEXP (op, 1));
1461 int ofs = INTVAL (XEXP (op, 2));
1462 if (bits == 16 && ofs == 0)
1463 fprintf (file, "%%lo16(");
1464 else if (bits == 16 && ofs == 16)
1465 fprintf (file, "%%hi16(");
1466 else if (bits == 8 && ofs == 16)
1467 fprintf (file, "%%hi8(");
1468 else
1469 gcc_unreachable ();
1470 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1471 fprintf (file, ")");
1473 break;
1475 case ZERO_EXTEND:
1476 if (GET_CODE (XEXP (op, 0)) == REG)
1477 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1478 else
1479 print_rtl (file, op);
1480 break;
1482 case PLUS:
1483 need_paren = 0;
1484 if (letter == 'H')
1486 fprintf (file, "%%hi16(");
1487 need_paren = 1;
1488 letter = 0;
1490 if (letter == 'h')
1492 fprintf (file, "%%lo16(");
1493 need_paren = 1;
1494 letter = 0;
1496 if (letter == 'e')
1498 fprintf (file, "%%hi8(");
1499 need_paren = 1;
1500 letter = 0;
1502 if (letter == 'q' || letter == 'Q')
1503 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1505 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1507 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1508 fprintf (file, "+");
1509 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1511 else
1513 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1514 fprintf (file, "+");
1515 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1517 if (need_paren)
1518 fprintf (file, ")");
1519 break;
1521 case SYMBOL_REF:
1522 need_paren = 0;
1523 if (letter == 'H')
1525 fprintf (file, "%%hi16(");
1526 need_paren = 1;
1527 letter = 0;
1529 if (letter == 'h')
1531 fprintf (file, "%%lo16(");
1532 need_paren = 1;
1533 letter = 0;
1535 if (letter == 'e')
1537 fprintf (file, "%%hi8(");
1538 need_paren = 1;
1539 letter = 0;
1541 if (letter == 'q' || letter == 'Q')
1542 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1544 output_addr_const (file, op);
1545 if (need_paren)
1546 fprintf (file, ")");
1547 break;
1549 case CODE_LABEL:
1550 case LABEL_REF:
1551 output_asm_label (op);
1552 break;
1554 case LTU:
1555 if (letter == 'z')
1556 fprintf (file, "#comparison eliminated");
1557 else
1558 fprintf (file, letter == 'c' ? "nc" : "c");
1559 break;
1560 case LEU:
1561 if (letter == 'z')
1562 fprintf (file, "br");
1563 else
1564 fprintf (file, letter == 'c' ? "h" : "nh");
1565 break;
1566 case GEU:
1567 if (letter == 'z')
1568 fprintf (file, "br");
1569 else
1570 fprintf (file, letter == 'c' ? "c" : "nc");
1571 break;
1572 case GTU:
1573 if (letter == 'z')
1574 fprintf (file, "#comparison eliminated");
1575 else
1576 fprintf (file, letter == 'c' ? "nh" : "h");
1577 break;
1578 case EQ:
1579 if (letter == 'z')
1580 fprintf (file, "br");
1581 else
1582 fprintf (file, letter == 'c' ? "nz" : "z");
1583 break;
1584 case NE:
1585 if (letter == 'z')
1586 fprintf (file, "#comparison eliminated");
1587 else
1588 fprintf (file, letter == 'c' ? "z" : "nz");
1589 break;
1591 /* Note: these assume appropriate adjustments were made so that
1592 unsigned comparisons, which is all this chip has, will
1593 work. */
1594 case LT:
1595 if (letter == 'z')
1596 fprintf (file, "#comparison eliminated");
1597 else
1598 fprintf (file, letter == 'c' ? "nc" : "c");
1599 break;
1600 case LE:
1601 if (letter == 'z')
1602 fprintf (file, "br");
1603 else
1604 fprintf (file, letter == 'c' ? "h" : "nh");
1605 break;
1606 case GE:
1607 if (letter == 'z')
1608 fprintf (file, "br");
1609 else
1610 fprintf (file, letter == 'c' ? "c" : "nc");
1611 break;
1612 case GT:
1613 if (letter == 'z')
1614 fprintf (file, "#comparison eliminated");
1615 else
1616 fprintf (file, letter == 'c' ? "nh" : "h");
1617 break;
1619 default:
1620 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1621 break;
1625 #undef TARGET_PRINT_OPERAND
1626 #define TARGET_PRINT_OPERAND rl78_print_operand
1628 static void
1629 rl78_print_operand (FILE * file, rtx op, int letter)
1631 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
1632 fprintf (file, "#");
1633 rl78_print_operand_1 (file, op, letter);
1636 #undef TARGET_TRAMPOLINE_INIT
1637 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1639 /* Note that the RL78's addressing makes it very difficult to do
1640 trampolines on the stack. So, libgcc has a small pool of
1641 trampolines from which one is allocated to this task. */
1642 static void
1643 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1645 rtx mov_addr, thunk_addr;
1646 rtx function = XEXP (DECL_RTL (fndecl), 0);
1648 mov_addr = adjust_address (m_tramp, HImode, 0);
1649 thunk_addr = gen_reg_rtx (HImode);
1651 function = force_reg (HImode, function);
1652 static_chain = force_reg (HImode, static_chain);
1654 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1655 emit_move_insn (mov_addr, thunk_addr);
1657 cfun->machine->trampolines_used = 1;
1660 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1661 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1663 static rtx
1664 rl78_trampoline_adjust_address (rtx m_tramp)
1666 rtx x = gen_rtx_MEM (HImode, m_tramp);
1667 return x;
1670 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1671 the "normal" compares, specifically, it only has unsigned compares,
1672 so we must synthesize the missing ones. */
1673 void
1674 rl78_expand_compare (rtx *operands)
1676 if (GET_CODE (operands[2]) == MEM)
1677 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1682 /* Define this to 1 if you are debugging the peephole optimizers. */
1683 #define DEBUG_PEEP 0
1685 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1686 The default "word" size is a byte so we can effectively use all the
1687 registers, but we want to do 16-bit moves whenever possible. This
1688 function determines when such a move is an option. */
1689 bool
1690 rl78_peep_movhi_p (rtx *operands)
1692 int i;
1693 rtx m, a;
1695 /* (set (op0) (op1))
1696 (set (op2) (op3)) */
1698 if (! rl78_virt_insns_ok ())
1699 return false;
1701 #if DEBUG_PEEP
1702 fprintf (stderr, "\033[33m");
1703 debug_rtx (operands[0]);
1704 debug_rtx (operands[1]);
1705 debug_rtx (operands[2]);
1706 debug_rtx (operands[3]);
1707 fprintf (stderr, "\033[0m");
1708 #endif
1710 /* You can move a constant to memory as QImode, but not HImode. */
1711 if (GET_CODE (operands[0]) == MEM
1712 && GET_CODE (operands[1]) != REG)
1714 #if DEBUG_PEEP
1715 fprintf (stderr, "no peep: move constant to memory\n");
1716 #endif
1717 return false;
1720 if (rtx_equal_p (operands[0], operands[3]))
1722 #if DEBUG_PEEP
1723 fprintf (stderr, "no peep: overlapping\n");
1724 #endif
1725 return false;
1728 for (i = 0; i < 2; i ++)
1730 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1732 #if DEBUG_PEEP
1733 fprintf (stderr, "no peep: different codes\n");
1734 #endif
1735 return false;
1737 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1739 #if DEBUG_PEEP
1740 fprintf (stderr, "no peep: different modes\n");
1741 #endif
1742 return false;
1745 switch (GET_CODE (operands[i]))
1747 case REG:
1748 /* LSB MSB */
1749 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1750 || GET_MODE (operands[i]) != QImode)
1752 #if DEBUG_PEEP
1753 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1754 REGNO (operands[i]), REGNO (operands[i+2]),
1756 #endif
1757 return false;
1759 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1761 #if DEBUG_PEEP
1762 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1763 #endif
1764 return false;
1766 break;
1768 case CONST_INT:
1769 break;
1771 case MEM:
1772 if (GET_MODE (operands[i]) != QImode)
1773 return false;
1774 if (MEM_ALIGN (operands[i]) < 16)
1775 return false;
1776 a = XEXP (operands[i], 0);
1777 if (GET_CODE (a) == CONST)
1778 a = XEXP (a, 0);
1779 if (GET_CODE (a) == PLUS)
1780 a = XEXP (a, 1);
1781 if (GET_CODE (a) == CONST_INT
1782 && INTVAL (a) & 1)
1784 #if DEBUG_PEEP
1785 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1786 debug_rtx (operands[i]);
1787 #endif
1788 return false;
1790 m = adjust_address (operands[i], QImode, 1);
1791 if (! rtx_equal_p (m, operands[i+2]))
1793 #if DEBUG_PEEP
1794 fprintf (stderr, "no peep: wrong mem %d\n", i);
1795 debug_rtx(m);
1796 debug_rtx (operands[i+2]);
1797 #endif
1798 return false;
1800 break;
1802 default:
1803 #if DEBUG_PEEP
1804 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1805 #endif
1806 return false;
1809 #if DEBUG_PEEP
1810 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1811 #endif
1812 return true;
1815 /* Likewise, when a peephole is activated, this function helps compute
1816 the new operands. */
1817 void
1818 rl78_setup_peep_movhi (rtx *operands)
1820 int i;
1822 for (i = 0; i < 2; i ++)
1824 switch (GET_CODE (operands[i]))
1826 case REG:
1827 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1828 break;
1830 case CONST_INT:
1831 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1832 break;
1834 case MEM:
1835 operands[i+4] = adjust_address (operands[i], HImode, 0);
1836 break;
1838 default:
1839 break;
1845 How Devirtualization works in the RL78 GCC port
1847 Background
1849 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1850 bytes of register space, in four banks, memory-mapped. One bank is
1851 the "selected" bank and holds the registers used for primary
1852 operations. Since the registers are memory mapped, often you can
1853 still refer to the unselected banks via memory accesses.
1855 Virtual Registers
1857 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1858 and refers to the other banks via their memory addresses, although
1859 they're treated as regular registers internally. These "virtual"
1860 registers are R8 through R23 (bank3 is reserved for asm-based
1861 interrupt handlers).
1863 There are four machine description files:
1865 rl78.md - common register-independent patterns and definitions
1866 rl78-expand.md - expanders
1867 rl78-virt.md - patterns that match BEFORE devirtualization
1868 rl78-real.md - patterns that match AFTER devirtualization
1870 At least through register allocation and reload, gcc is told that it
1871 can do pretty much anything - but may only use the virtual registers.
1872 GCC cannot properly create the varying addressing modes that the RL78
1873 supports in an efficient way.
1875 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1876 uses the "valloc" attribute in rl78-virt.md for determining the rules
1877 by which it will replace virtual registers with real registers (or
1878 not) and how to make up addressing modes. For example, insns tagged
1879 with "ro1" have a single read-only parameter, which may need to be
1880 moved from memory/constant/vreg to a suitable real register. As part
1881 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1882 patterns and enabling the rl78-real.md patterns. The new patterns'
1883 constraints are used to determine the real registers used. NOTE:
1884 patterns in rl78-virt.md essentially ignore the constrains and rely on
1885 predicates, where the rl78-real.md ones essentially ignore the
1886 predicates and rely on the constraints.
1888 The devirtualization pass is scheduled via the pass manager (despite
1889 being called "rl78_reorg") so it can be scheduled prior to var-track
1890 (the idea is to let gdb know about the new registers). Ideally, it
1891 would be scheduled right after pro/epilogue generation, so the
1892 post-reload optimizers could operate on the real registers, but when I
1893 tried that there were some issues building the target libraries.
1895 During devirtualization, a simple register move optimizer is run. It
1896 would be better to run a full CSE/propogation pass on it through, or
1897 re-run regmove, but that has not yet been attempted.
1900 #define DEBUG_ALLOC 0
1902 #define OP(x) (*recog_data.operand_loc[x])
1904 /* This array is used to hold knowledge about the contents of the
1905 real registers (A ... H), the memory-based registers (r8 ... r31)
1906 and the first NUM_STACK_LOCS words on the stack. We use this to
1907 avoid generating redundant move instructions.
1909 A value in the range 0 .. 31 indicates register A .. r31.
1910 A value in the range 32 .. 63 indicates stack slot (value - 32).
1911 A value of NOT_KNOWN indicates that the contents of that location
1912 are not known. */
1914 #define NUM_STACK_LOCS 32
1915 #define NOT_KNOWN 127
1917 static unsigned char content_memory [32 + NUM_STACK_LOCS];
1919 static unsigned char saved_update_index = NOT_KNOWN;
1920 static unsigned char saved_update_value;
1921 static enum machine_mode saved_update_mode;
1924 static inline void
1925 clear_content_memory (void)
1927 memset (content_memory, NOT_KNOWN, sizeof content_memory);
1928 if (dump_file)
1929 fprintf (dump_file, " clear content memory\n");
1930 saved_update_index = NOT_KNOWN;
1933 /* Convert LOC into an index into the content_memory array.
1934 If LOC cannot be converted, return NOT_KNOWN. */
1936 static unsigned char
1937 get_content_index (rtx loc)
1939 enum machine_mode mode;
1941 if (loc == NULL_RTX)
1942 return NOT_KNOWN;
1944 if (REG_P (loc))
1946 if (REGNO (loc) < 32)
1947 return REGNO (loc);
1948 return NOT_KNOWN;
1951 mode = GET_MODE (loc);
1953 if (! rl78_stack_based_mem (loc, mode))
1954 return NOT_KNOWN;
1956 loc = XEXP (loc, 0);
1958 if (REG_P (loc))
1959 /* loc = MEM (SP) */
1960 return 32;
1962 /* loc = MEM (PLUS (SP, INT)). */
1963 loc = XEXP (loc, 1);
1965 if (INTVAL (loc) < NUM_STACK_LOCS)
1966 return 32 + INTVAL (loc);
1968 return NOT_KNOWN;
1971 /* Return a string describing content INDEX in mode MODE.
1972 WARNING: Can return a pointer to a static buffer. */
1973 static const char *
1974 get_content_name (unsigned char index, enum machine_mode mode)
1976 static char buffer [128];
1978 if (index == NOT_KNOWN)
1979 return "Unknown";
1981 if (index > 31)
1982 sprintf (buffer, "stack slot %d", index - 32);
1983 else if (mode == HImode)
1984 sprintf (buffer, "%s%s",
1985 reg_names [index + 1], reg_names [index]);
1986 else
1987 return reg_names [index];
1989 return buffer;
1992 #if DEBUG_ALLOC
1994 static void
1995 display_content_memory (FILE * file)
1997 unsigned int i;
1999 fprintf (file, " Known memory contents:\n");
2001 for (i = 0; i < sizeof content_memory; i++)
2002 if (content_memory[i] != NOT_KNOWN)
2004 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2005 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2008 #endif
2010 static void
2011 update_content (unsigned char index, unsigned char val, enum machine_mode mode)
2013 unsigned int i;
2015 gcc_assert (index < sizeof content_memory);
2017 content_memory [index] = val;
2018 if (val != NOT_KNOWN)
2019 content_memory [val] = index;
2021 /* Make the entry in dump_file *before* VAL is increased below. */
2022 if (dump_file)
2024 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2025 if (val == NOT_KNOWN)
2026 fprintf (dump_file, "Unknown\n");
2027 else
2028 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2031 if (mode == HImode)
2033 val = val == NOT_KNOWN ? val : val + 1;
2035 content_memory [index + 1] = val;
2036 if (val != NOT_KNOWN)
2038 content_memory [val] = index + 1;
2039 -- val;
2043 /* Any other places that had INDEX recorded as their contents are now invalid. */
2044 for (i = 0; i < sizeof content_memory; i++)
2046 if (i == index
2047 || (val != NOT_KNOWN && i == val))
2049 if (mode == HImode)
2050 ++ i;
2051 continue;
2054 if (content_memory[i] == index
2055 || (val != NOT_KNOWN && content_memory[i] == val))
2057 content_memory[i] = NOT_KNOWN;
2059 if (dump_file)
2060 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2062 if (mode == HImode)
2063 content_memory[++ i] = NOT_KNOWN;
2068 /* Record that LOC contains VALUE.
2069 For HImode locations record that LOC+1 contains VALUE+1.
2070 If LOC is not a register or stack slot, do nothing.
2071 If VALUE is not a register or stack slot, clear the recorded content. */
2073 static void
2074 record_content (rtx loc, rtx value)
2076 enum machine_mode mode;
2077 unsigned char index;
2078 unsigned char val;
2080 if ((index = get_content_index (loc)) == NOT_KNOWN)
2081 return;
2083 val = get_content_index (value);
2085 mode = GET_MODE (loc);
2087 if (val == index)
2089 if (! optimize)
2090 return;
2092 /* This should not happen when optimizing. */
2093 #if 1
2094 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2095 get_content_name (val, mode));
2096 return;
2097 #else
2098 gcc_unreachable ();
2099 #endif
2102 update_content (index, val, mode);
2105 /* Returns TRUE if LOC already contains a copy of VALUE. */
2107 static bool
2108 already_contains (rtx loc, rtx value)
2110 unsigned char index;
2111 unsigned char val;
2113 if ((index = get_content_index (loc)) == NOT_KNOWN)
2114 return false;
2116 if ((val = get_content_index (value)) == NOT_KNOWN)
2117 return false;
2119 if (content_memory [index] != val)
2120 return false;
2122 if (GET_MODE (loc) == HImode)
2123 return content_memory [index + 1] == val + 1;
2125 return true;
2128 bool
2129 rl78_es_addr (rtx addr)
2131 if (GET_CODE (addr) == MEM)
2132 addr = XEXP (addr, 0);
2133 if (GET_CODE (addr) != UNSPEC)
2134 return false;
2135 if (XINT (addr, 1) != UNS_ES_ADDR)
2136 return false;
2137 return true;
2141 rl78_es_base (rtx addr)
2143 if (GET_CODE (addr) == MEM)
2144 addr = XEXP (addr, 0);
2145 addr = XVECEXP (addr, 0, 1);
2146 if (GET_CODE (addr) == CONST
2147 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2148 addr = XEXP (XEXP (addr, 0), 0);
2149 /* Mode doesn't matter here. */
2150 return gen_rtx_MEM (HImode, addr);
2153 /* Rescans an insn to see if it's recognized again. This is done
2154 carefully to ensure that all the constraint information is accurate
2155 for the newly matched insn. */
2156 static bool
2157 insn_ok_now (rtx insn)
2159 rtx pattern = PATTERN (insn);
2160 int i;
2162 INSN_CODE (insn) = -1;
2164 if (recog (pattern, insn, 0) > -1)
2166 extract_insn (insn);
2167 if (constrain_operands (1))
2169 #if DEBUG_ALLOC
2170 fprintf (stderr, "\033[32m");
2171 debug_rtx (insn);
2172 fprintf (stderr, "\033[0m");
2173 #endif
2174 if (SET_P (pattern))
2175 record_content (SET_DEST (pattern), SET_SRC (pattern));
2177 /* We need to detect far addresses that haven't been
2178 converted to es/lo16 format. */
2179 for (i=0; i<recog_data.n_operands; i++)
2180 if (GET_CODE (OP (i)) == MEM
2181 && GET_MODE (XEXP (OP (i), 0)) == SImode
2182 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2183 return false;
2185 return true;
2188 else
2190 /* We need to re-recog the insn with virtual registers to get
2191 the operands. */
2192 cfun->machine->virt_insns_ok = 1;
2193 if (recog (pattern, insn, 0) > -1)
2195 extract_insn (insn);
2196 if (constrain_operands (0))
2198 cfun->machine->virt_insns_ok = 0;
2199 return false;
2203 #if DEBUG_ALLOC
2204 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2205 debug_rtx (insn);
2206 #endif
2207 gcc_unreachable ();
2210 #if DEBUG_ALLOC
2211 fprintf (stderr, "\033[31m");
2212 debug_rtx (insn);
2213 fprintf (stderr, "\033[0m");
2214 #endif
2215 return false;
2218 #if DEBUG_ALLOC
2219 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2220 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2221 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2222 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2223 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2224 #else
2225 #define FAILED gcc_unreachable ()
2226 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2227 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2228 #endif
2230 /* Registers into which we move the contents of virtual registers. */
2231 #define X gen_rtx_REG (QImode, X_REG)
2232 #define A gen_rtx_REG (QImode, A_REG)
2233 #define C gen_rtx_REG (QImode, C_REG)
2234 #define B gen_rtx_REG (QImode, B_REG)
2235 #define E gen_rtx_REG (QImode, E_REG)
2236 #define D gen_rtx_REG (QImode, D_REG)
2237 #define L gen_rtx_REG (QImode, L_REG)
2238 #define H gen_rtx_REG (QImode, H_REG)
2240 #define AX gen_rtx_REG (HImode, AX_REG)
2241 #define BC gen_rtx_REG (HImode, BC_REG)
2242 #define DE gen_rtx_REG (HImode, DE_REG)
2243 #define HL gen_rtx_REG (HImode, HL_REG)
2245 /* Returns TRUE if R is a virtual register. */
2246 static inline bool
2247 is_virtual_register (rtx r)
2249 return (GET_CODE (r) == REG
2250 && REGNO (r) >= 8
2251 && REGNO (r) < 32);
2254 /* In all these alloc routines, we expect the following: the insn
2255 pattern is unshared, the insn was previously recognized and failed
2256 due to predicates or constraints, and the operand data is in
2257 recog_data. */
2259 static int virt_insn_was_frame;
2261 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2262 needed. */
2263 static rtx
2264 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2266 #if DEBUG_ALLOC
2267 fprintf (stderr, "\033[36m%d: ", line);
2268 debug_rtx(r);
2269 fprintf (stderr, "\033[0m");
2270 #endif
2271 /*SCHED_GROUP_P (r) = 1;*/
2272 if (virt_insn_was_frame)
2273 RTX_FRAME_RELATED_P (r) = 1;
2274 return r;
2277 #define EM(x) EM2 (__LINE__, x)
2279 /* Return a suitable RTX for the low half of a __far address. */
2280 static rtx
2281 rl78_lo16 (rtx addr)
2283 rtx r;
2285 if (GET_CODE (addr) == SYMBOL_REF
2286 || GET_CODE (addr) == CONST)
2288 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2289 r = gen_rtx_CONST (HImode, r);
2291 else
2292 r = rl78_subreg (HImode, addr, SImode, 0);
2294 r = gen_es_addr (r);
2296 return r;
2299 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2300 static rtx
2301 rl78_hi8 (rtx addr)
2303 if (GET_CODE (addr) == SYMBOL_REF
2304 || GET_CODE (addr) == CONST)
2306 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2307 r = gen_rtx_CONST (QImode, r);
2308 return r;
2310 return rl78_subreg (QImode, addr, SImode, 2);
2313 static void
2314 add_postponed_content_update (rtx to, rtx value)
2316 unsigned char index;
2318 if ((index = get_content_index (to)) == NOT_KNOWN)
2319 return;
2321 gcc_assert (saved_update_index == NOT_KNOWN);
2322 saved_update_index = index;
2323 saved_update_value = get_content_index (value);
2324 saved_update_mode = GET_MODE (to);
2327 static void
2328 process_postponed_content_update (void)
2330 if (saved_update_index != NOT_KNOWN)
2332 update_content (saved_update_index, saved_update_value, saved_update_mode);
2333 saved_update_index = NOT_KNOWN;
2337 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2338 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2339 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2340 BEFORE is true, FROM otherwise. */
2341 static rtx
2342 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2344 enum machine_mode mode = GET_MODE (to);
2346 if (optimize && before && already_contains (to, from))
2348 #if DEBUG_ALLOC
2349 display_content_memory (stderr);
2350 #endif
2351 if (dump_file)
2353 fprintf (dump_file, " Omit move of %s into ",
2354 get_content_name (get_content_index (from), mode));
2355 fprintf (dump_file, "%s as it already contains this value\n",
2356 get_content_name (get_content_index (to), mode));
2359 else
2361 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2363 EM (move);
2365 if (where == NULL_RTX)
2366 emit_insn (move);
2367 else if (before)
2368 emit_insn_before (move, where);
2369 else
2371 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2373 /* If necessary move REG_EH_REGION notes forward.
2374 cf. compiling gcc.dg/pr44545.c. */
2375 if (note != NULL_RTX)
2377 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2378 remove_note (where, note);
2381 emit_insn_after (move, where);
2384 if (before)
2385 record_content (to, from);
2386 else
2387 add_postponed_content_update (to, from);
2390 return before ? to : from;
2393 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2394 copy it into NEWBASE and return the updated MEM. Otherwise just
2395 return M. Any needed insns are emitted before BEFORE. */
2396 static rtx
2397 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2399 rtx base, index, addendr;
2400 int addend = 0;
2401 int need_es = 0;
2403 if (! MEM_P (m))
2404 return m;
2406 if (GET_MODE (XEXP (m, 0)) == SImode)
2408 rtx new_m;
2409 rtx seg = rl78_hi8 (XEXP (m, 0));
2411 #if DEBUG_ALLOC
2412 fprintf (stderr, "setting ES:\n");
2413 debug_rtx(seg);
2414 #endif
2415 emit_insn_before (EM (gen_movqi (A, seg)), before);
2416 emit_insn_before (EM (gen_movqi_es (A)), before);
2417 record_content (A, NULL_RTX);
2419 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2420 MEM_COPY_ATTRIBUTES (new_m, m);
2421 m = new_m;
2422 need_es = 1;
2425 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2426 gcc_assert (index == NULL_RTX);
2428 #if DEBUG_ALLOC
2429 fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m");
2430 debug_rtx (base);
2431 #endif
2432 if (base == NULL_RTX)
2433 return m;
2435 if (addendr && GET_CODE (addendr) == CONST_INT)
2436 addend = INTVAL (addendr);
2438 gcc_assert (REG_P (base));
2439 gcc_assert (REG_P (newbase));
2441 if (REGNO (base) == SP_REG)
2443 if (addend >= 0 && addend <= 255)
2444 return m;
2447 /* BASE should be a virtual register. We copy it to NEWBASE. If
2448 the addend is out of range for DE/HL, we use AX to compute the full
2449 address. */
2451 if (addend < 0
2452 || (addend > 255 && REGNO (newbase) != 2)
2453 || (addendr && GET_CODE (addendr) != CONST_INT))
2455 /* mov ax, vreg
2456 add ax, #imm
2457 mov hl, ax */
2458 EM (emit_insn_before (gen_movhi (AX, base), before));
2459 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2460 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2461 record_content (AX, NULL_RTX);
2462 record_content (newbase, NULL_RTX);
2464 base = newbase;
2465 addend = 0;
2467 else
2469 base = gen_and_emit_move (newbase, base, before, true);
2472 if (addend)
2474 record_content (base, NULL_RTX);
2475 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2478 #if DEBUG_ALLOC
2479 fprintf (stderr, "\033[33m");
2480 debug_rtx (m);
2481 #endif
2482 if (need_es)
2483 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2484 else
2485 m = change_address (m, GET_MODE (m), base);
2486 #if DEBUG_ALLOC
2487 debug_rtx (m);
2488 fprintf (stderr, "\033[0m");
2489 #endif
2490 return m;
2493 /* Copy SRC to accumulator (A or AX), placing any generated insns
2494 before BEFORE. Returns accumulator RTX. */
2495 static rtx
2496 move_to_acc (int opno, rtx before)
2498 rtx src = OP (opno);
2499 enum machine_mode mode = GET_MODE (src);
2501 if (REG_P (src) && REGNO (src) < 2)
2502 return src;
2504 if (mode == VOIDmode)
2505 mode = recog_data.operand_mode[opno];
2507 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2510 static void
2511 force_into_acc (rtx src, rtx before)
2513 enum machine_mode mode = GET_MODE (src);
2514 rtx move;
2516 if (REG_P (src) && REGNO (src) < 2)
2517 return;
2519 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2521 EM (move);
2523 emit_insn_before (move, before);
2524 record_content (AX, NULL_RTX);
2527 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2528 after AFTER. Returns accumulator RTX. */
2529 static rtx
2530 move_from_acc (unsigned int opno, rtx after)
2532 rtx dest = OP (opno);
2533 enum machine_mode mode = GET_MODE (dest);
2535 if (REG_P (dest) && REGNO (dest) < 2)
2536 return dest;
2538 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2541 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2542 before BEFORE. Returns reg RTX. */
2543 static rtx
2544 move_acc_to_reg (rtx acc, int regno, rtx before)
2546 enum machine_mode mode = GET_MODE (acc);
2547 rtx reg;
2549 reg = gen_rtx_REG (mode, regno);
2551 return gen_and_emit_move (reg, acc, before, true);
2554 /* Copy SRC to X, placing any generated insns before BEFORE.
2555 Returns X RTX. */
2556 static rtx
2557 move_to_x (int opno, rtx before)
2559 rtx src = OP (opno);
2560 enum machine_mode mode = GET_MODE (src);
2561 rtx reg;
2563 if (mode == VOIDmode)
2564 mode = recog_data.operand_mode[opno];
2565 reg = (mode == QImode) ? X : AX;
2567 if (mode == QImode || ! is_virtual_register (OP (opno)))
2569 OP (opno) = move_to_acc (opno, before);
2570 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
2571 return reg;
2574 return gen_and_emit_move (reg, src, before, true);
2577 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2578 Returns H/HL RTX. */
2579 static rtx
2580 move_to_hl (int opno, rtx before)
2582 rtx src = OP (opno);
2583 enum machine_mode mode = GET_MODE (src);
2584 rtx reg;
2586 if (mode == VOIDmode)
2587 mode = recog_data.operand_mode[opno];
2588 reg = (mode == QImode) ? L : HL;
2590 if (mode == QImode || ! is_virtual_register (OP (opno)))
2592 OP (opno) = move_to_acc (opno, before);
2593 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2594 return reg;
2597 return gen_and_emit_move (reg, src, before, true);
2600 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2601 Returns E/DE RTX. */
2602 static rtx
2603 move_to_de (int opno, rtx before)
2605 rtx src = OP (opno);
2606 enum machine_mode mode = GET_MODE (src);
2607 rtx reg;
2609 if (mode == VOIDmode)
2610 mode = recog_data.operand_mode[opno];
2612 reg = (mode == QImode) ? E : DE;
2614 if (mode == QImode || ! is_virtual_register (OP (opno)))
2616 OP (opno) = move_to_acc (opno, before);
2617 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2619 else
2621 gen_and_emit_move (reg, src, before, true);
2624 return reg;
2627 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2628 static void
2629 rl78_alloc_physical_registers_op1 (rtx insn)
2631 /* op[0] = func op[1] */
2633 /* We first try using A as the destination, then copying it
2634 back. */
2635 if (rtx_equal_p (OP (0), OP (1)))
2637 OP (0) =
2638 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2640 else
2642 /* If necessary, load the operands into BC and HL.
2643 Check to see if we already have OP (0) in HL
2644 and if so, swap the order. */
2645 if (MEM_P (OP (0))
2646 && already_contains (HL, XEXP (OP (0), 0)))
2648 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2649 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2651 else
2653 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2654 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2658 MAYBE_OK (insn);
2660 OP (0) = move_from_acc (0, insn);
2662 MAYBE_OK (insn);
2664 /* Try copying the src to acc first, then. This is for, for
2665 example, ZERO_EXTEND or NOT. */
2666 OP (1) = move_to_acc (1, insn);
2668 MUST_BE_OK (insn);
2671 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2672 Assumes that the current insn has already been recognised and hence the
2673 constraint data has been filled in. */
2674 static bool
2675 has_constraint (unsigned int opnum, enum constraint_num constraint)
2677 const char * p = recog_data.constraints[opnum];
2679 /* No constraints means anything is accepted. */
2680 if (p == NULL || *p == 0 || *p == ',')
2681 return true;
2685 char c;
2686 unsigned int len;
2688 c = *p;
2689 len = CONSTRAINT_LEN (c, p);
2690 gcc_assert (len > 0);
2692 switch (c)
2694 case 0:
2695 case ',':
2696 return false;
2697 default:
2698 if (lookup_constraint (p) == constraint)
2699 return true;
2701 p += len;
2703 while (1);
2706 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2707 static void
2708 rl78_alloc_physical_registers_op2 (rtx insn)
2710 rtx prev;
2711 rtx first;
2712 bool hl_used;
2713 int tmp_id;
2714 rtx saved_op1;
2716 if (rtx_equal_p (OP (0), OP (1)))
2718 OP (0) =
2719 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2720 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2722 else if (rtx_equal_p (OP (0), OP (2)))
2724 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2725 OP (0) =
2726 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2728 else
2730 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2731 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2732 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2735 MAYBE_OK (insn);
2737 prev = prev_nonnote_nondebug_insn (insn);
2738 if (recog_data.constraints[1][0] == '%'
2739 && is_virtual_register (OP (1))
2740 && ! is_virtual_register (OP (2))
2741 && ! CONSTANT_P (OP (2)))
2743 rtx tmp = OP (1);
2744 OP (1) = OP (2);
2745 OP (2) = tmp;
2748 /* Make a note of whether (H)L is being used. It matters
2749 because if OP (2) alsoneeds reloading, then we must take
2750 care not to corrupt HL. */
2751 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2753 /* If HL is not currently being used and dest == op1 then there are
2754 some possible optimizations available by reloading one of the
2755 operands into HL, before trying to use the accumulator. */
2756 if (optimize
2757 && ! hl_used
2758 && rtx_equal_p (OP (0), OP (1)))
2760 /* If op0 is a Ws1 type memory address then switching the base
2761 address register to HL might allow us to perform an in-memory
2762 operation. (eg for the INCW instruction).
2764 FIXME: Adding the move into HL is costly if this optimization is not
2765 going to work, so for now, make sure that we know that the new insn will
2766 match the requirements of the addhi3_real pattern. Really we ought to
2767 generate a candidate sequence, test that, and then install it if the
2768 results are good. */
2769 if (satisfies_constraint_Ws1 (OP (0))
2770 && has_constraint (0, CONSTRAINT_Wh1)
2771 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2773 rtx base, index, addend, newbase;
2775 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
2776 gcc_assert (index == NULL_RTX);
2777 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2779 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2780 if (addend != NULL_RTX)
2782 newbase = gen_and_emit_move (HL, base, insn, true);
2783 record_content (newbase, NULL_RTX);
2784 newbase = gen_rtx_PLUS (HImode, newbase, addend);
2786 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
2788 /* We do not want to fail here as this means that
2789 we have inserted useless insns into the stream. */
2790 MUST_BE_OK (insn);
2793 else if (REG_P (OP (0))
2794 && satisfies_constraint_Ws1 (OP (2))
2795 && has_constraint (2, CONSTRAINT_Wh1))
2797 rtx base, index, addend, newbase;
2799 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
2800 gcc_assert (index == NULL_RTX);
2801 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2803 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2804 if (addend != NULL_RTX)
2806 gen_and_emit_move (HL, base, insn, true);
2808 if (REGNO (OP (0)) != X_REG)
2810 OP (1) = move_to_acc (1, insn);
2811 OP (0) = move_from_acc (0, insn);
2814 record_content (HL, NULL_RTX);
2815 newbase = gen_rtx_PLUS (HImode, HL, addend);
2817 OP (2) = change_address (OP (2), VOIDmode, newbase);
2819 /* We do not want to fail here as this means that
2820 we have inserted useless insns into the stream. */
2821 MUST_BE_OK (insn);
2826 OP (0) = move_from_acc (0, insn);
2828 tmp_id = get_max_insn_count ();
2829 saved_op1 = OP (1);
2831 if (rtx_equal_p (OP (1), OP (2)))
2832 OP (2) = OP (1) = move_to_acc (1, insn);
2833 else
2834 OP (1) = move_to_acc (1, insn);
2836 MAYBE_OK (insn);
2838 /* If we omitted the move of OP1 into the accumulator (because
2839 it was already there from a previous insn), then force the
2840 generation of the move instruction now. We know that we
2841 are about to emit a move into HL (or DE) via AX, and hence
2842 our optimization to remove the load of OP1 is no longer valid. */
2843 if (tmp_id == get_max_insn_count ())
2844 force_into_acc (saved_op1, insn);
2846 /* We have to copy op2 to HL (or DE), but that involves AX, which
2847 already has a live value. Emit it before those insns. */
2849 if (prev)
2850 first = next_nonnote_nondebug_insn (prev);
2851 else
2852 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2855 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2857 MUST_BE_OK (insn);
2860 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2861 static void
2862 rl78_alloc_physical_registers_ro1 (rtx insn)
2864 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2866 MAYBE_OK (insn);
2868 OP (0) = move_to_acc (0, insn);
2870 MUST_BE_OK (insn);
2873 /* Devirtualize a compare insn. */
2874 static void
2875 rl78_alloc_physical_registers_cmp (rtx insn)
2877 int tmp_id;
2878 rtx saved_op1;
2879 rtx prev = prev_nonnote_nondebug_insn (insn);
2880 rtx first;
2882 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2883 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2885 /* HI compares have to have OP (1) in AX, but QI
2886 compares do not, so it is worth checking here. */
2887 MAYBE_OK (insn);
2889 /* For an HImode compare, OP (1) must always be in AX.
2890 But if OP (1) is a REG (and not AX), then we can avoid
2891 a reload of OP (1) if we reload OP (2) into AX and invert
2892 the comparison. */
2893 if (REG_P (OP (1))
2894 && REGNO (OP (1)) != AX_REG
2895 && GET_MODE (OP (1)) == HImode
2896 && MEM_P (OP (2)))
2898 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
2900 OP (2) = move_to_acc (2, insn);
2902 switch (GET_CODE (cmp))
2904 case EQ:
2905 case NE:
2906 break;
2907 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
2908 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
2909 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
2910 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
2912 case LT:
2913 case GT:
2914 case LE:
2915 case GE:
2916 #if DEBUG_ALLOC
2917 debug_rtx (insn);
2918 #endif
2919 default:
2920 gcc_unreachable ();
2923 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
2924 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
2925 else
2926 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
2928 MUST_BE_OK (insn);
2931 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2932 should be handled by the second alternative of the cbranchhi_real pattern. */
2933 if (rtx_equal_p (OP (1), OP (2)))
2935 OP (1) = OP (2) = BC;
2936 MUST_BE_OK (insn);
2939 tmp_id = get_max_insn_count ();
2940 saved_op1 = OP (1);
2942 OP (1) = move_to_acc (1, insn);
2944 MAYBE_OK (insn);
2946 /* If we omitted the move of OP1 into the accumulator (because
2947 it was already there from a previous insn), then force the
2948 generation of the move instruction now. We know that we
2949 are about to emit a move into HL via AX, and hence our
2950 optimization to remove the load of OP1 is no longer valid. */
2951 if (tmp_id == get_max_insn_count ())
2952 force_into_acc (saved_op1, insn);
2954 /* We have to copy op2 to HL, but that involves the acc, which
2955 already has a live value. Emit it before those insns. */
2956 if (prev)
2957 first = next_nonnote_nondebug_insn (prev);
2958 else
2959 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2961 OP (2) = move_to_hl (2, first);
2963 MUST_BE_OK (insn);
2966 /* Like op2, but AX = A op X. */
2967 static void
2968 rl78_alloc_physical_registers_umul (rtx insn)
2970 rtx prev = prev_nonnote_nondebug_insn (insn);
2971 rtx first;
2972 int tmp_id;
2973 rtx saved_op1;
2975 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2976 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2977 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2979 MAYBE_OK (insn);
2981 if (recog_data.constraints[1][0] == '%'
2982 && is_virtual_register (OP (1))
2983 && !is_virtual_register (OP (2))
2984 && !CONSTANT_P (OP (2)))
2986 rtx tmp = OP (1);
2987 OP (1) = OP (2);
2988 OP (2) = tmp;
2991 OP (0) = move_from_acc (0, insn);
2993 tmp_id = get_max_insn_count ();
2994 saved_op1 = OP (1);
2996 OP (1) = move_to_acc (1, insn);
2998 MAYBE_OK (insn);
3000 /* If we omitted the move of OP1 into the accumulator (because
3001 it was already there from a previous insn), then force the
3002 generation of the move instruction now. We know that we
3003 are about to emit a move into HL (or DE) via AX, and hence
3004 our optimization to remove the load of OP1 is no longer valid. */
3005 if (tmp_id == get_max_insn_count ())
3006 force_into_acc (saved_op1, insn);
3008 /* We have to copy op2 to X, but that involves the acc, which
3009 already has a live value. Emit it before those insns. */
3011 if (prev)
3012 first = next_nonnote_nondebug_insn (prev);
3013 else
3014 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3016 OP (2) = move_to_x (2, first);
3018 MUST_BE_OK (insn);
3021 static void
3022 rl78_alloc_address_registers_macax (rtx insn)
3024 int which, op;
3025 bool replace_in_op0 = false;
3026 bool replace_in_op1 = false;
3028 MAYBE_OK (insn);
3030 /* Two different MEMs are not allowed. */
3031 which = 0;
3032 for (op = 2; op >= 0; op --)
3034 if (MEM_P (OP (op)))
3036 if (op == 0 && replace_in_op0)
3037 continue;
3038 if (op == 1 && replace_in_op1)
3039 continue;
3041 switch (which)
3043 case 0:
3044 /* If we replace a MEM, make sure that we replace it for all
3045 occurrences of the same MEM in the insn. */
3046 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3047 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3049 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3050 if (op == 2
3051 && MEM_P (OP (op))
3052 && (REGNO (XEXP (OP (op), 0)) == SP_REG
3053 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3054 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3056 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3057 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3059 if (replace_in_op0)
3060 OP (0) = OP (op);
3061 if (replace_in_op1)
3062 OP (1) = OP (op);
3063 break;
3064 case 1:
3065 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3066 break;
3067 case 2:
3068 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3069 break;
3071 which ++;
3075 MUST_BE_OK (insn);
3078 /* Scan all insns and devirtualize them. */
3079 static void
3080 rl78_alloc_physical_registers (void)
3082 /* During most of the compile, gcc is dealing with virtual
3083 registers. At this point, we need to assign physical registers
3084 to the vitual ones, and copy in/out as needed. */
3086 rtx insn, curr;
3087 enum attr_valloc valloc_method;
3089 for (insn = get_insns (); insn; insn = curr)
3091 int i;
3093 curr = next_nonnote_nondebug_insn (insn);
3095 if (INSN_P (insn)
3096 && (GET_CODE (PATTERN (insn)) == SET
3097 || GET_CODE (PATTERN (insn)) == CALL)
3098 && INSN_CODE (insn) == -1)
3100 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3101 continue;
3102 i = recog (PATTERN (insn), insn, 0);
3103 if (i == -1)
3105 debug_rtx (insn);
3106 gcc_unreachable ();
3108 INSN_CODE (insn) = i;
3112 cfun->machine->virt_insns_ok = 0;
3113 cfun->machine->real_insns_ok = 1;
3115 clear_content_memory ();
3117 for (insn = get_insns (); insn; insn = curr)
3119 rtx pattern;
3121 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3123 if (!INSN_P (insn))
3125 if (LABEL_P (insn))
3126 clear_content_memory ();
3128 continue;
3131 if (dump_file)
3132 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3134 pattern = PATTERN (insn);
3135 if (GET_CODE (pattern) == PARALLEL)
3136 pattern = XVECEXP (pattern, 0, 0);
3137 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3138 clear_content_memory ();
3139 if (GET_CODE (pattern) != SET
3140 && GET_CODE (pattern) != CALL)
3141 continue;
3142 if (GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3143 continue;
3145 valloc_method = get_attr_valloc (insn);
3147 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3149 if (valloc_method == VALLOC_MACAX)
3151 record_content (AX, NULL_RTX);
3152 record_content (BC, NULL_RTX);
3153 record_content (DE, NULL_RTX);
3156 if (insn_ok_now (insn))
3157 continue;
3159 INSN_CODE (insn) = -1;
3161 if (RTX_FRAME_RELATED_P (insn))
3162 virt_insn_was_frame = 1;
3163 else
3164 virt_insn_was_frame = 0;
3166 switch (valloc_method)
3168 case VALLOC_OP1:
3169 rl78_alloc_physical_registers_op1 (insn);
3170 break;
3171 case VALLOC_OP2:
3172 rl78_alloc_physical_registers_op2 (insn);
3173 break;
3174 case VALLOC_RO1:
3175 rl78_alloc_physical_registers_ro1 (insn);
3176 break;
3177 case VALLOC_CMP:
3178 rl78_alloc_physical_registers_cmp (insn);
3179 break;
3180 case VALLOC_UMUL:
3181 rl78_alloc_physical_registers_umul (insn);
3182 break;
3183 case VALLOC_MACAX:
3184 /* Macro that clobbers AX. */
3185 rl78_alloc_address_registers_macax (insn);
3186 record_content (AX, NULL_RTX);
3187 record_content (BC, NULL_RTX);
3188 record_content (DE, NULL_RTX);
3189 break;
3192 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3193 clear_content_memory ();
3194 else
3195 process_postponed_content_update ();
3198 #if DEBUG_ALLOC
3199 fprintf (stderr, "\033[0m");
3200 #endif
3203 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3204 This function scans for uses of registers; the last use (i.e. first
3205 encounter when scanning backwards) triggers a REG_DEAD note if the
3206 reg was previously in DEAD[]. */
3207 static void
3208 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3210 const char *fmt;
3211 int i, r;
3212 enum rtx_code code;
3214 if (!s)
3215 return;
3217 code = GET_CODE (s);
3219 switch (code)
3221 /* Compare registers by number. */
3222 case REG:
3223 r = REGNO (s);
3224 if (dump_file)
3226 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3227 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3228 print_rtl_single (dump_file, s);
3230 if (dead [r])
3231 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3232 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3233 dead [r + i] = 0;
3234 return;
3236 /* These codes have no constituent expressions
3237 and are unique. */
3238 case SCRATCH:
3239 case CC0:
3240 case PC:
3241 return;
3243 case CONST_INT:
3244 case CONST_VECTOR:
3245 case CONST_DOUBLE:
3246 case CONST_FIXED:
3247 /* These are kept unique for a given value. */
3248 return;
3250 default:
3251 break;
3254 fmt = GET_RTX_FORMAT (code);
3256 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3258 if (fmt[i] == 'E')
3260 int j;
3261 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3262 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3264 else if (fmt[i] == 'e')
3265 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3269 /* Like the previous function, but scan for SETs instead. */
3270 static void
3271 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3273 int r, i;
3275 if (GET_CODE (d) != REG)
3276 return;
3278 r = REGNO (d);
3279 if (dead [r])
3280 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3281 if (dump_file)
3282 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3283 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3284 dead [r + i] = 1;
3287 /* This is a rather crude register death pass. Death status is reset
3288 at every jump or call insn. */
3289 static void
3290 rl78_calculate_death_notes (void)
3292 char dead[FIRST_PSEUDO_REGISTER];
3293 rtx insn, p, s, d;
3294 int i;
3296 memset (dead, 0, sizeof (dead));
3298 for (insn = get_last_insn ();
3299 insn;
3300 insn = prev_nonnote_nondebug_insn (insn))
3302 if (dump_file)
3304 fprintf (dump_file, "\n--------------------------------------------------");
3305 fprintf (dump_file, "\nDead:");
3306 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3307 if (dead[i])
3308 fprintf (dump_file, " %s", reg_names[i]);
3309 fprintf (dump_file, "\n");
3310 print_rtl_single (dump_file, insn);
3313 switch (GET_CODE (insn))
3315 case INSN:
3316 p = PATTERN (insn);
3317 switch (GET_CODE (p))
3319 case SET:
3320 s = SET_SRC (p);
3321 d = SET_DEST (p);
3322 rl78_note_reg_set (dead, d, insn);
3323 rl78_note_reg_uses (dead, s, insn);
3324 break;
3326 case USE:
3327 rl78_note_reg_uses (dead, p, insn);
3328 break;
3330 default:
3331 break;
3333 break;
3335 case JUMP_INSN:
3336 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3338 memset (dead, 1, sizeof (dead));
3339 /* We expect a USE just prior to this, which will mark
3340 the actual return registers. The USE will have a
3341 death note, but we aren't going to be modifying it
3342 after this pass. */
3343 break;
3345 case CALL_INSN:
3346 memset (dead, 0, sizeof (dead));
3347 break;
3349 default:
3350 break;
3352 if (dump_file)
3353 print_rtl_single (dump_file, insn);
3357 /* Helper function to reset the origins in RP and the age in AGE for
3358 all registers. */
3359 static void
3360 reset_origins (int *rp, int *age)
3362 int i;
3363 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3365 rp[i] = i;
3366 age[i] = 0;
3370 /* The idea behind this optimization is to look for cases where we
3371 move data from A to B to C, and instead move from A to B, and A to
3372 C. If B is a virtual register or memory, this is a big win on its
3373 own. If B turns out to be unneeded after this, it's a bigger win.
3374 For each register, we try to determine where it's value originally
3375 came from, if it's propogated purely through moves (and not
3376 computes). The ORIGINS[] array has the regno for the "origin" of
3377 the value in the [regno] it's indexed by. */
3378 static void
3379 rl78_propogate_register_origins (void)
3381 int origins[FIRST_PSEUDO_REGISTER];
3382 int age[FIRST_PSEUDO_REGISTER];
3383 int i;
3384 rtx insn, ninsn = NULL_RTX;
3385 rtx pat;
3387 reset_origins (origins, age);
3389 for (insn = get_insns (); insn; insn = ninsn)
3391 ninsn = next_nonnote_nondebug_insn (insn);
3393 if (dump_file)
3395 fprintf (dump_file, "\n");
3396 fprintf (dump_file, "Origins:");
3397 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3398 if (origins[i] != i)
3399 fprintf (dump_file, " r%d=r%d", i, origins[i]);
3400 fprintf (dump_file, "\n");
3401 print_rtl_single (dump_file, insn);
3404 switch (GET_CODE (insn))
3406 case CODE_LABEL:
3407 case BARRIER:
3408 case CALL_INSN:
3409 case JUMP_INSN:
3410 reset_origins (origins, age);
3411 break;
3413 default:
3414 break;
3416 case INSN:
3417 pat = PATTERN (insn);
3419 if (GET_CODE (pat) == PARALLEL)
3421 rtx clobber = XVECEXP (pat, 0, 1);
3422 pat = XVECEXP (pat, 0, 0);
3423 if (GET_CODE (clobber) == CLOBBER)
3425 int cr = REGNO (XEXP (clobber, 0));
3426 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3427 if (dump_file)
3428 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3429 for (i = 0; i < mb; i++)
3431 origins[cr + i] = cr + i;
3432 age[cr + i] = 0;
3435 else
3436 break;
3439 if (GET_CODE (pat) == SET)
3441 rtx src = SET_SRC (pat);
3442 rtx dest = SET_DEST (pat);
3443 int mb = GET_MODE_SIZE (GET_MODE (dest));
3445 if (GET_CODE (dest) == REG)
3447 int dr = REGNO (dest);
3449 if (GET_CODE (src) == REG)
3451 int sr = REGNO (src);
3452 int same = 1;
3453 int best_age, best_reg;
3455 /* See if the copy is not needed. */
3456 for (i = 0; i < mb; i ++)
3457 if (origins[dr + i] != origins[sr + i])
3458 same = 0;
3459 if (same)
3461 if (dump_file)
3462 fprintf (dump_file, "deleting because dest already has correct value\n");
3463 delete_insn (insn);
3464 break;
3467 if (dr < 8 || sr >= 8)
3469 int ar;
3471 best_age = -1;
3472 best_reg = -1;
3473 /* See if the copy can be made from another
3474 bank 0 register instead, instead of the
3475 virtual src register. */
3476 for (ar = 0; ar < 8; ar += mb)
3478 same = 1;
3479 for (i = 0; i < mb; i ++)
3480 if (origins[ar + i] != origins[sr + i])
3481 same = 0;
3483 /* The chip has some reg-reg move limitations. */
3484 if (mb == 1 && dr > 3)
3485 same = 0;
3487 if (same)
3489 if (best_age == -1 || best_age > age[sr + i])
3491 best_age = age[sr + i];
3492 best_reg = sr;
3497 if (best_reg != -1)
3499 /* FIXME: copy debug info too. */
3500 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3501 sr = best_reg;
3505 for (i = 0; i < mb; i++)
3507 origins[dr + i] = origins[sr + i];
3508 age[dr + i] = age[sr + i] + 1;
3511 else
3513 /* The destination is computed, its origin is itself. */
3514 if (dump_file)
3515 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3516 dr, mb, mb == 1 ? "" : "s");
3517 for (i = 0; i < mb; i ++)
3519 origins[dr + i] = dr + i;
3520 age[dr + i] = 0;
3524 /* Any registers marked with that reg as an origin are reset. */
3525 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3526 if (origins[i] >= dr && origins[i] < dr + mb)
3528 origins[i] = i;
3529 age[i] = 0;
3533 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3534 if (get_attr_valloc (insn) == VALLOC_MACAX)
3536 if (dump_file)
3537 fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
3538 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3539 if (i <= 3 || origins[i] <= 3)
3541 origins[i] = i;
3542 age[i] = 0;
3546 if (GET_CODE (src) == ASHIFT
3547 || GET_CODE (src) == ASHIFTRT
3548 || GET_CODE (src) == LSHIFTRT)
3550 rtx count = XEXP (src, 1);
3551 if (GET_CODE (count) == REG)
3553 /* Special case - our pattern clobbers the count register. */
3554 int r = REGNO (count);
3555 if (dump_file)
3556 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3557 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3558 if (i == r || origins[i] == r)
3560 origins[i] = i;
3561 age[i] = 0;
3566 else if (GET_CODE (pat) == CLOBBER)
3568 if (REG_P (XEXP (pat, 0)))
3570 unsigned int reg = REGNO (XEXP (pat, 0));
3572 origins[reg] = reg;
3573 age[reg] = 0;
3580 /* Remove any SETs where the destination is unneeded. */
3581 static void
3582 rl78_remove_unused_sets (void)
3584 rtx insn, ninsn = NULL_RTX;
3585 rtx dest;
3587 for (insn = get_insns (); insn; insn = ninsn)
3589 ninsn = next_nonnote_nondebug_insn (insn);
3591 if ((insn = single_set (insn)) == NULL_RTX)
3592 continue;
3594 dest = SET_DEST (insn);
3596 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3597 continue;
3599 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3600 delete_insn (insn);
3604 /* This is the top of the devritualization pass. */
3605 static void
3606 rl78_reorg (void)
3608 /* split2 only happens when optimizing, but we need all movSIs to be
3609 split now. */
3610 if (optimize <= 0)
3611 split_all_insns ();
3613 rl78_alloc_physical_registers ();
3615 if (dump_file)
3617 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3618 print_rtl_with_bb (dump_file, get_insns (), 0);
3621 rl78_propogate_register_origins ();
3622 rl78_calculate_death_notes ();
3624 if (dump_file)
3626 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3627 print_rtl_with_bb (dump_file, get_insns (), 0);
3628 fprintf (dump_file, "\n======================================================================\n");
3631 rl78_remove_unused_sets ();
3633 /* The code after devirtualizing has changed so much that at this point
3634 we might as well just rescan everything. Note that
3635 df_rescan_all_insns is not going to help here because it does not
3636 touch the artificial uses and defs. */
3637 df_finish_pass (true);
3638 if (optimize > 1)
3639 df_live_add_problem ();
3640 df_scan_alloc (NULL);
3641 df_scan_blocks ();
3643 if (optimize)
3644 df_analyze ();
3647 #undef TARGET_RETURN_IN_MEMORY
3648 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3650 static bool
3651 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3653 const HOST_WIDE_INT size = int_size_in_bytes (type);
3654 return (size == -1 || size > 8);
3658 #undef TARGET_RTX_COSTS
3659 #define TARGET_RTX_COSTS rl78_rtx_costs
3661 static bool rl78_rtx_costs (rtx x,
3662 int code,
3663 int outer_code ATTRIBUTE_UNUSED,
3664 int opno ATTRIBUTE_UNUSED,
3665 int * total,
3666 bool speed ATTRIBUTE_UNUSED)
3668 if (code == IF_THEN_ELSE)
3669 return COSTS_N_INSNS (10);
3670 if (GET_MODE (x) == SImode)
3672 switch (code)
3674 case MULT:
3675 if (RL78_MUL_RL78)
3676 *total = COSTS_N_INSNS (14);
3677 else if (RL78_MUL_G13)
3678 *total = COSTS_N_INSNS (29);
3679 else
3680 *total = COSTS_N_INSNS (500);
3681 return true;
3682 case PLUS:
3683 *total = COSTS_N_INSNS (8);
3684 return true;
3685 case ASHIFT:
3686 case ASHIFTRT:
3687 case LSHIFTRT:
3688 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3690 switch (INTVAL (XEXP (x, 1)))
3692 case 0: *total = COSTS_N_INSNS (0); break;
3693 case 1: *total = COSTS_N_INSNS (6); break;
3694 case 2: case 3: case 4: case 5: case 6: case 7:
3695 *total = COSTS_N_INSNS (10); break;
3696 case 8: *total = COSTS_N_INSNS (6); break;
3697 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3698 *total = COSTS_N_INSNS (10); break;
3699 case 16: *total = COSTS_N_INSNS (3); break;
3700 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3701 *total = COSTS_N_INSNS (4); break;
3702 case 24: *total = COSTS_N_INSNS (4); break;
3703 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3704 *total = COSTS_N_INSNS (5); break;
3707 else
3708 *total = COSTS_N_INSNS (10+4*16);
3709 return true;
3712 return false;
3716 #undef TARGET_UNWIND_WORD_MODE
3717 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3719 static enum machine_mode
3720 rl78_unwind_word_mode (void)
3722 return HImode;
3726 struct gcc_target targetm = TARGET_INITIALIZER;
3728 #include "gt-rl78.h"