Fixups after merge
[official-gcc.git] / gcc / config / rl78 / rl78.c
blob7b85cf83d9d077083f5ec3144bec581e1f66e438
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2014 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "varasm.h"
27 #include "stor-layout.h"
28 #include "calls.h"
29 #include "rtl.h"
30 #include "regs.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "hashtab.h"
38 #include "hash-set.h"
39 #include "vec.h"
40 #include "machmode.h"
41 #include "input.h"
42 #include "function.h"
43 #include "expr.h"
44 #include "insn-codes.h"
45 #include "optabs.h"
46 #include "libfuncs.h"
47 #include "recog.h"
48 #include "diagnostic-core.h"
49 #include "toplev.h"
50 #include "reload.h"
51 #include "dominance.h"
52 #include "cfg.h"
53 #include "cfgrtl.h"
54 #include "cfganal.h"
55 #include "lcm.h"
56 #include "cfgbuild.h"
57 #include "cfgcleanup.h"
58 #include "predict.h"
59 #include "basic-block.h"
60 #include "df.h"
61 #include "ggc.h"
62 #include "tm_p.h"
63 #include "debug.h"
64 #include "target.h"
65 #include "target-def.h"
66 #include "langhooks.h"
67 #include "rl78-protos.h"
68 #include "dumpfile.h"
69 #include "tree-pass.h"
70 #include "context.h"
71 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
72 #include "insn-flags.h" /* for gen_*(). */
73 #include "builtins.h"
75 static inline bool is_interrupt_func (const_tree decl);
76 static inline bool is_brk_interrupt_func (const_tree decl);
77 static void rl78_reorg (void);
80 /* Debugging statements are tagged with DEBUG0 only so that they can
81 be easily enabled individually, by replacing the '0' with '1' as
82 needed. */
83 #define DEBUG0 0
84 #define DEBUG1 1
86 /* REGISTER_NAMES has the names for individual 8-bit registers, but
87 these have the names we need to use when referring to 16-bit
88 register pairs. */
89 static const char * const word_regnames[] =
91 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
92 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
93 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
94 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
95 "sp", "ap", "psw", "es", "cs"
98 struct GTY(()) machine_function
100 /* If set, the rest of the fields have been computed. */
101 int computed;
102 /* Which register pairs need to be pushed in the prologue. */
103 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
105 /* These fields describe the frame layout... */
106 /* arg pointer */
107 /* 4 bytes for saved PC */
108 int framesize_regs;
109 /* frame pointer */
110 int framesize_locals;
111 int framesize_outgoing;
112 /* stack pointer */
113 int framesize;
115 /* If set, recog is allowed to match against the "real" patterns. */
116 int real_insns_ok;
117 /* If set, recog is allowed to match against the "virtual" patterns. */
118 int virt_insns_ok;
119 /* Set if the current function needs to clean up any trampolines. */
120 int trampolines_used;
123 /* This is our init_machine_status, as set in
124 rl78_option_override. */
125 static struct machine_function *
126 rl78_init_machine_status (void)
128 struct machine_function *m;
130 m = ggc_cleared_alloc<machine_function> ();
131 m->virt_insns_ok = 1;
133 return m;
136 /* This pass converts virtual instructions using virtual registers, to
137 real instructions using real registers. Rather than run it as
138 reorg, we reschedule it before vartrack to help with debugging. */
139 namespace {
141 const pass_data pass_data_rl78_devirt =
143 RTL_PASS, /* type */
144 "devirt", /* name */
145 OPTGROUP_NONE, /* optinfo_flags */
146 TV_MACH_DEP, /* tv_id */
147 0, /* properties_required */
148 0, /* properties_provided */
149 0, /* properties_destroyed */
150 0, /* todo_flags_start */
151 0, /* todo_flags_finish */
154 class pass_rl78_devirt : public rtl_opt_pass
156 public:
157 pass_rl78_devirt(gcc::context *ctxt)
158 : rtl_opt_pass(pass_data_rl78_devirt, ctxt)
162 /* opt_pass methods: */
163 virtual unsigned int execute (function *)
165 rl78_reorg ();
166 return 0;
171 } // anon namespace
173 rtl_opt_pass *
174 make_pass_rl78_devirt (gcc::context *ctxt)
176 return new pass_rl78_devirt (ctxt);
179 /* Redundant move elimination pass. Must be run after the basic block
180 reordering pass for the best effect. */
182 static unsigned int
183 move_elim_pass (void)
185 rtx_insn *insn, *ninsn;
186 rtx prev = NULL_RTX;
188 for (insn = get_insns (); insn; insn = ninsn)
190 rtx set;
192 ninsn = next_nonnote_nondebug_insn (insn);
194 if ((set = single_set (insn)) == NULL_RTX)
196 prev = NULL_RTX;
197 continue;
200 /* If we have two SET insns in a row (without anything
201 between them) and the source of the second one is the
202 destination of the first one, and vice versa, then we
203 can eliminate the second SET. */
204 if (prev
205 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
206 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
209 if (dump_file)
210 fprintf (dump_file, " Delete insn %d because it is redundant\n",
211 INSN_UID (insn));
213 delete_insn (insn);
214 prev = NULL_RTX;
216 else
217 prev = set;
220 if (dump_file)
221 print_rtl_with_bb (dump_file, get_insns (), 0);
223 return 0;
226 namespace {
228 const pass_data pass_data_rl78_move_elim =
230 RTL_PASS, /* type */
231 "move_elim", /* name */
232 OPTGROUP_NONE, /* optinfo_flags */
233 TV_MACH_DEP, /* tv_id */
234 0, /* properties_required */
235 0, /* properties_provided */
236 0, /* properties_destroyed */
237 0, /* todo_flags_start */
238 0, /* todo_flags_finish */
241 class pass_rl78_move_elim : public rtl_opt_pass
243 public:
244 pass_rl78_move_elim(gcc::context *ctxt)
245 : rtl_opt_pass(pass_data_rl78_move_elim, ctxt)
249 /* opt_pass methods: */
250 virtual unsigned int execute (function *) { return move_elim_pass (); }
253 } // anon namespace
255 rtl_opt_pass *
256 make_pass_rl78_move_elim (gcc::context *ctxt)
258 return new pass_rl78_move_elim (ctxt);
261 #undef TARGET_ASM_FILE_START
262 #define TARGET_ASM_FILE_START rl78_asm_file_start
264 static void
265 rl78_asm_file_start (void)
267 int i;
269 if (TARGET_G10)
271 /* The memory used is 0xffec8 to 0xffedf; real registers are in
272 0xffee0 to 0xffee7. */
273 for (i = 8; i < 32; i++)
274 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
276 else
278 for (i = 0; i < 8; i++)
280 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
281 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
282 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 24 + i, 0xffee0 + i);
286 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
287 static struct register_pass_info rl78_devirt_info =
289 rl78_devirt_pass,
290 "pro_and_epilogue",
292 PASS_POS_INSERT_BEFORE
295 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
296 static struct register_pass_info rl78_move_elim_info =
298 rl78_move_elim_pass,
299 "bbro",
301 PASS_POS_INSERT_AFTER
304 register_pass (& rl78_devirt_info);
305 register_pass (& rl78_move_elim_info);
309 #undef TARGET_OPTION_OVERRIDE
310 #define TARGET_OPTION_OVERRIDE rl78_option_override
312 static void
313 rl78_option_override (void)
315 flag_omit_frame_pointer = 1;
316 flag_no_function_cse = 1;
317 flag_split_wide_types = 0;
319 init_machine_status = rl78_init_machine_status;
321 if (TARGET_ALLREGS)
323 int i;
325 for (i = 24; i < 32; i++)
326 fixed_regs[i] = 0;
330 /* Most registers are 8 bits. Some are 16 bits because, for example,
331 gcc doesn't like dealing with $FP as a register pair (the second
332 half of $fp is also 2 to keep reload happy wrt register pairs, but
333 no register class includes it). This table maps register numbers
334 to size in bytes. */
335 static const int register_sizes[] =
337 1, 1, 1, 1, 1, 1, 1, 1,
338 1, 1, 1, 1, 1, 1, 1, 1,
339 1, 1, 1, 1, 1, 1, 2, 2,
340 1, 1, 1, 1, 1, 1, 1, 1,
341 2, 2, 1, 1, 1
344 /* Predicates used in the MD patterns. This one is true when virtual
345 insns may be matched, which typically means before (or during) the
346 devirt pass. */
347 bool
348 rl78_virt_insns_ok (void)
350 if (cfun)
351 return cfun->machine->virt_insns_ok;
352 return true;
355 /* Predicates used in the MD patterns. This one is true when real
356 insns may be matched, which typically means after (or during) the
357 devirt pass. */
358 bool
359 rl78_real_insns_ok (void)
361 if (cfun)
362 return cfun->machine->real_insns_ok;
363 return false;
366 /* Implements HARD_REGNO_NREGS. */
368 rl78_hard_regno_nregs (int regno, machine_mode mode)
370 int rs = register_sizes[regno];
371 if (rs < 1)
372 rs = 1;
373 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
376 /* Implements HARD_REGNO_MODE_OK. */
378 rl78_hard_regno_mode_ok (int regno, machine_mode mode)
380 int s = GET_MODE_SIZE (mode);
382 if (s < 1)
383 return 0;
384 /* These are not to be used by gcc. */
385 if (regno == 23 || regno == ES_REG || regno == CS_REG)
386 return 0;
387 /* $fp can always be accessed as a 16-bit value. */
388 if (regno == FP_REG && s == 2)
389 return 1;
390 if (regno < SP_REG)
392 /* Since a reg-reg move is really a reg-mem move, we must
393 enforce alignment. */
394 if (s > 1 && (regno % 2))
395 return 0;
396 return 1;
398 if (s == CC_REGNUM)
399 return (mode == BImode);
400 /* All other registers must be accessed in their natural sizes. */
401 if (s == register_sizes [regno])
402 return 1;
403 return 0;
406 /* Simplify_gen_subreg() doesn't handle memory references the way we
407 need it to below, so we use this function for when we must get a
408 valid subreg in a "natural" state. */
409 static rtx
410 rl78_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
412 if (GET_CODE (r) == MEM)
413 return adjust_address (r, mode, byte);
414 else
415 return simplify_gen_subreg (mode, r, omode, byte);
418 /* Used by movsi. Split SImode moves into two HImode moves, using
419 appropriate patterns for the upper and lower halves of symbols. */
420 void
421 rl78_expand_movsi (rtx *operands)
423 rtx op00, op02, op10, op12;
425 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
426 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
427 if (GET_CODE (operands[1]) == CONST
428 || GET_CODE (operands[1]) == SYMBOL_REF)
430 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
431 op10 = gen_rtx_CONST (HImode, op10);
432 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
433 op12 = gen_rtx_CONST (HImode, op12);
435 else
437 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
438 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
441 if (rtx_equal_p (operands[0], operands[1]))
443 else if (rtx_equal_p (op00, op12))
445 emit_move_insn (op02, op12);
446 emit_move_insn (op00, op10);
448 else
450 emit_move_insn (op00, op10);
451 emit_move_insn (op02, op12);
455 /* Generate code to move an SImode value. */
456 void
457 rl78_split_movsi (rtx *operands)
459 rtx op00, op02, op10, op12;
461 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
462 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
464 if (GET_CODE (operands[1]) == CONST
465 || GET_CODE (operands[1]) == SYMBOL_REF)
467 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
468 op10 = gen_rtx_CONST (HImode, op10);
469 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
470 op12 = gen_rtx_CONST (HImode, op12);
472 else
474 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
475 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
478 if (rtx_equal_p (operands[0], operands[1]))
480 else if (rtx_equal_p (op00, op12))
482 operands[2] = op02;
483 operands[4] = op12;
484 operands[3] = op00;
485 operands[5] = op10;
487 else
489 operands[2] = op00;
490 operands[4] = op10;
491 operands[3] = op02;
492 operands[5] = op12;
496 /* Used by various two-operand expanders which cannot accept all
497 operands in the "far" namespace. Force some such operands into
498 registers so that each pattern has at most one far operand. */
500 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
502 int did = 0;
503 rtx temp_reg = NULL;
505 /* FIXME: in the future, be smarter about only doing this if the
506 other operand is also far, assuming the devirtualizer can also
507 handle that. */
508 if (rl78_far_p (operands[0]))
510 temp_reg = operands[0];
511 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
512 did = 1;
514 if (!did)
515 return 0;
517 emit_insn (gen (operands[0], operands[1]));
518 if (temp_reg)
519 emit_move_insn (temp_reg, operands[0]);
520 return 1;
523 /* Likewise, but for three-operand expanders. */
525 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
527 int did = 0;
528 rtx temp_reg = NULL;
530 /* FIXME: Likewise. */
531 if (rl78_far_p (operands[1]))
533 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
534 emit_move_insn (temp_reg, operands[1]);
535 operands[1] = temp_reg;
536 did = 1;
538 if (rl78_far_p (operands[0]))
540 temp_reg = operands[0];
541 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
542 did = 1;
544 if (!did)
545 return 0;
547 emit_insn (gen (operands[0], operands[1], operands[2]));
548 if (temp_reg)
549 emit_move_insn (temp_reg, operands[0]);
550 return 1;
553 #undef TARGET_CAN_ELIMINATE
554 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
556 static bool
557 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
559 return true;
562 /* Returns true if the given register needs to be saved by the
563 current function. */
564 static bool
565 need_to_save (unsigned int regno)
567 if (is_interrupt_func (cfun->decl))
569 /* We don't know what devirt will need */
570 if (regno < 8)
571 return true;
573 /* We don't need to save registers that have
574 been reserved for interrupt handlers. */
575 if (regno > 23)
576 return false;
578 /* If the handler is a non-leaf function then it may call
579 non-interrupt aware routines which will happily clobber
580 any call_used registers, so we have to preserve them. */
581 if (!crtl->is_leaf && call_used_regs[regno])
582 return true;
584 /* Otherwise we only have to save a register, call_used
585 or not, if it is used by this handler. */
586 return df_regs_ever_live_p (regno);
589 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
590 return true;
591 if (fixed_regs[regno])
592 return false;
593 if (crtl->calls_eh_return)
594 return true;
595 if (df_regs_ever_live_p (regno)
596 && !call_used_regs[regno])
597 return true;
598 return false;
601 /* We use this to wrap all emitted insns in the prologue. */
602 static rtx
603 F (rtx x)
605 RTX_FRAME_RELATED_P (x) = 1;
606 return x;
609 /* Compute all the frame-related fields in our machine_function
610 structure. */
611 static void
612 rl78_compute_frame_info (void)
614 int i;
616 cfun->machine->computed = 1;
617 cfun->machine->framesize_regs = 0;
618 cfun->machine->framesize_locals = get_frame_size ();
619 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
621 for (i = 0; i < 16; i ++)
622 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
624 cfun->machine->need_to_push [i] = 1;
625 cfun->machine->framesize_regs += 2;
627 else
628 cfun->machine->need_to_push [i] = 0;
630 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
631 cfun->machine->framesize_locals ++;
633 cfun->machine->framesize = (cfun->machine->framesize_regs
634 + cfun->machine->framesize_locals
635 + cfun->machine->framesize_outgoing);
638 /* Returns true if the provided function has the specified attribute. */
639 static inline bool
640 has_func_attr (const_tree decl, const char * func_attr)
642 if (decl == NULL_TREE)
643 decl = current_function_decl;
645 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
648 /* Returns true if the provided function has the "interrupt" attribute. */
649 static inline bool
650 is_interrupt_func (const_tree decl)
652 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
655 /* Returns true if the provided function has the "brk_interrupt" attribute. */
656 static inline bool
657 is_brk_interrupt_func (const_tree decl)
659 return has_func_attr (decl, "brk_interrupt");
662 /* Check "interrupt" attributes. */
663 static tree
664 rl78_handle_func_attribute (tree * node,
665 tree name,
666 tree args,
667 int flags ATTRIBUTE_UNUSED,
668 bool * no_add_attrs)
670 gcc_assert (DECL_P (* node));
671 gcc_assert (args == NULL_TREE);
673 if (TREE_CODE (* node) != FUNCTION_DECL)
675 warning (OPT_Wattributes, "%qE attribute only applies to functions",
676 name);
677 * no_add_attrs = true;
680 /* FIXME: We ought to check that the interrupt and exception
681 handler attributes have been applied to void functions. */
682 return NULL_TREE;
685 #undef TARGET_ATTRIBUTE_TABLE
686 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
688 /* Table of RL78-specific attributes. */
689 const struct attribute_spec rl78_attribute_table[] =
691 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
692 affects_type_identity. */
693 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
694 false },
695 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
696 false },
697 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute,
698 false },
699 { NULL, 0, 0, false, false, false, NULL, false }
704 /* Break down an address RTX into its component base/index/addend
705 portions and return TRUE if the address is of a valid form, else
706 FALSE. */
707 static bool
708 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
710 *base = NULL_RTX;
711 *index = NULL_RTX;
712 *addend = NULL_RTX;
714 if (GET_CODE (x) == UNSPEC
715 && XINT (x, 1) == UNS_ES_ADDR)
716 x = XVECEXP (x, 0, 1);
718 if (GET_CODE (x) == REG)
720 *base = x;
721 return true;
724 /* We sometimes get these without the CONST wrapper */
725 if (GET_CODE (x) == PLUS
726 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
727 && GET_CODE (XEXP (x, 1)) == CONST_INT)
729 *addend = x;
730 return true;
733 if (GET_CODE (x) == PLUS)
735 *base = XEXP (x, 0);
736 x = XEXP (x, 1);
738 if (GET_CODE (*base) != REG
739 && GET_CODE (x) == REG)
741 rtx tmp = *base;
742 *base = x;
743 x = tmp;
746 if (GET_CODE (*base) != REG)
747 return false;
749 if (GET_CODE (x) == ZERO_EXTEND
750 && GET_CODE (XEXP (x, 0)) == REG)
752 *index = XEXP (x, 0);
753 return false;
757 switch (GET_CODE (x))
759 case PLUS:
760 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
761 && GET_CODE (XEXP (x, 0)) == CONST_INT)
763 *addend = x;
764 return true;
766 /* fall through */
767 case MEM:
768 case REG:
769 return false;
771 case CONST:
772 case SYMBOL_REF:
773 case CONST_INT:
774 *addend = x;
775 return true;
777 default:
778 return false;
781 return false;
784 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
785 addressing. */
786 bool
787 rl78_hl_b_c_addr_p (rtx op)
789 rtx hl, bc;
791 if (GET_CODE (op) != PLUS)
792 return false;
793 hl = XEXP (op, 0);
794 bc = XEXP (op, 1);
795 if (GET_CODE (hl) == ZERO_EXTEND)
797 rtx tmp = hl;
798 hl = bc;
799 bc = tmp;
801 if (GET_CODE (hl) != REG)
802 return false;
803 if (GET_CODE (bc) != ZERO_EXTEND)
804 return false;
805 bc = XEXP (bc, 0);
806 if (GET_CODE (bc) != REG)
807 return false;
808 if (REGNO (hl) != HL_REG)
809 return false;
810 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
811 return false;
813 return true;
816 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
818 /* Used in various constraints and predicates to match operands in the
819 "far" address space. */
821 rl78_far_p (rtx x)
823 if (! MEM_P (x))
824 return 0;
825 #if DEBUG0
826 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x);
827 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
828 #endif
829 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
832 /* Return the appropriate mode for a named address pointer. */
833 #undef TARGET_ADDR_SPACE_POINTER_MODE
834 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
835 static machine_mode
836 rl78_addr_space_pointer_mode (addr_space_t addrspace)
838 switch (addrspace)
840 case ADDR_SPACE_GENERIC:
841 return HImode;
842 case ADDR_SPACE_FAR:
843 return SImode;
844 default:
845 gcc_unreachable ();
849 /* Returns TRUE for valid addresses. */
850 #undef TARGET_VALID_POINTER_MODE
851 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
852 static bool
853 rl78_valid_pointer_mode (machine_mode m)
855 return (m == HImode || m == SImode);
858 /* Return the appropriate mode for a named address address. */
859 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
860 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
861 static machine_mode
862 rl78_addr_space_address_mode (addr_space_t addrspace)
864 switch (addrspace)
866 case ADDR_SPACE_GENERIC:
867 return HImode;
868 case ADDR_SPACE_FAR:
869 return SImode;
870 default:
871 gcc_unreachable ();
875 #undef TARGET_LEGITIMATE_CONSTANT_P
876 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
878 static bool
879 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
881 return true;
884 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
885 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
887 bool
888 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
889 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
891 rtx base, index, addend;
892 bool is_far_addr = false;
894 if (GET_CODE (x) == UNSPEC
895 && XINT (x, 1) == UNS_ES_ADDR)
897 x = XVECEXP (x, 0, 1);
898 is_far_addr = true;
901 if (as == ADDR_SPACE_GENERIC
902 && (GET_MODE (x) == SImode || is_far_addr))
903 return false;
905 if (! characterize_address (x, &base, &index, &addend))
906 return false;
908 /* We can't extract the high/low portions of a PLUS address
909 involving a register during devirtualization, so make sure all
910 such __far addresses do not have addends. This forces GCC to do
911 the sum separately. */
912 if (addend && base && as == ADDR_SPACE_FAR)
913 return false;
915 if (base && index)
917 int ir = REGNO (index);
918 int br = REGNO (base);
920 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
921 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
922 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
923 return false;
926 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
927 return false;
929 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
930 && REGNO (base) >= 8 && REGNO (base) <= 31)
931 return false;
933 return true;
936 /* Determine if one named address space is a subset of another. */
937 #undef TARGET_ADDR_SPACE_SUBSET_P
938 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
939 static bool
940 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
942 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
943 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
945 if (subset == superset)
946 return true;
948 else
949 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
952 #undef TARGET_ADDR_SPACE_CONVERT
953 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
954 /* Convert from one address space to another. */
955 static rtx
956 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
958 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
959 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
960 rtx result;
962 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
963 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
965 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
967 /* This is unpredictable, as we're truncating off usable address
968 bits. */
970 result = gen_reg_rtx (HImode);
971 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
972 return result;
974 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
976 /* This always works. */
977 result = gen_reg_rtx (SImode);
978 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
979 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
980 return result;
982 else
983 gcc_unreachable ();
986 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
987 bool
988 rl78_regno_mode_code_ok_for_base_p (int regno, machine_mode mode ATTRIBUTE_UNUSED,
989 addr_space_t address_space ATTRIBUTE_UNUSED,
990 int outer_code ATTRIBUTE_UNUSED, int index_code)
992 if (regno <= SP_REG && regno >= 16)
993 return true;
994 if (index_code == REG)
995 return (regno == HL_REG);
996 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
997 return true;
998 return false;
1001 /* Implements MODE_CODE_BASE_REG_CLASS. */
1002 enum reg_class
1003 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
1004 addr_space_t address_space ATTRIBUTE_UNUSED,
1005 int outer_code ATTRIBUTE_UNUSED,
1006 int index_code ATTRIBUTE_UNUSED)
1008 return V_REGS;
1011 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1012 described in the machine_Function struct definition, above. */
1014 rl78_initial_elimination_offset (int from, int to)
1016 int rv = 0; /* as if arg to arg */
1018 rl78_compute_frame_info ();
1020 switch (to)
1022 case STACK_POINTER_REGNUM:
1023 rv += cfun->machine->framesize_outgoing;
1024 rv += cfun->machine->framesize_locals;
1025 /* Fall through. */
1026 case FRAME_POINTER_REGNUM:
1027 rv += cfun->machine->framesize_regs;
1028 rv += 4;
1029 break;
1030 default:
1031 gcc_unreachable ();
1034 switch (from)
1036 case FRAME_POINTER_REGNUM:
1037 rv -= 4;
1038 rv -= cfun->machine->framesize_regs;
1039 case ARG_POINTER_REGNUM:
1040 break;
1041 default:
1042 gcc_unreachable ();
1045 return rv;
1048 static int
1049 rl78_is_naked_func (void)
1051 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1054 /* Expand the function prologue (from the prologue pattern). */
1055 void
1056 rl78_expand_prologue (void)
1058 int i, fs;
1059 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1060 int rb = 0;
1062 if (rl78_is_naked_func ())
1063 return;
1065 /* Always re-compute the frame info - the register usage may have changed. */
1066 rl78_compute_frame_info ();
1068 if (flag_stack_usage_info)
1069 current_function_static_stack_size = cfun->machine->framesize;
1071 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1072 for (i = 0; i < 4; i++)
1073 if (cfun->machine->need_to_push [i])
1075 /* Select Bank 0 if we are using any registers from Bank 0. */
1076 emit_insn (gen_sel_rb (GEN_INT (0)));
1077 break;
1080 for (i = 0; i < 16; i++)
1081 if (cfun->machine->need_to_push [i])
1083 if (TARGET_G10)
1085 emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
1086 F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
1088 else
1090 int need_bank = i/4;
1092 if (need_bank != rb)
1094 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1095 rb = need_bank;
1097 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
1101 if (rb != 0)
1102 emit_insn (gen_sel_rb (GEN_INT (0)));
1104 if (frame_pointer_needed)
1106 F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1107 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
1108 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
1109 gen_rtx_REG (HImode, AX_REG)));
1112 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1113 while (fs > 0)
1115 int fs_byte = (fs > 254) ? 254 : fs;
1116 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1117 fs -= fs_byte;
1121 /* Expand the function epilogue (from the epilogue pattern). */
1122 void
1123 rl78_expand_epilogue (void)
1125 int i, fs;
1126 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1127 int rb = 0;
1129 if (rl78_is_naked_func ())
1130 return;
1132 if (frame_pointer_needed)
1134 emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1135 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1136 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
1137 gen_rtx_REG (HImode, AX_REG));
1139 else
1141 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1142 while (fs > 0)
1144 int fs_byte = (fs > 254) ? 254 : fs;
1146 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1147 fs -= fs_byte;
1151 for (i = 15; i >= 0; i--)
1152 if (cfun->machine->need_to_push [i])
1154 rtx dest = gen_rtx_REG (HImode, i * 2);
1156 if (TARGET_G10)
1158 rtx ax = gen_rtx_REG (HImode, 0);
1160 emit_insn (gen_pop (ax));
1161 if (i != 0)
1163 emit_move_insn (dest, ax);
1164 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1165 emit_insn (gen_use (dest));
1168 else
1170 int need_bank = i / 4;
1172 if (need_bank != rb)
1174 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1175 rb = need_bank;
1177 emit_insn (gen_pop (dest));
1181 if (rb != 0)
1182 emit_insn (gen_sel_rb (GEN_INT (0)));
1184 if (cfun->machine->trampolines_used)
1185 emit_insn (gen_trampoline_uninit ());
1187 if (is_brk_interrupt_func (cfun->decl))
1188 emit_jump_insn (gen_brk_interrupt_return ());
1189 else if (is_interrupt_func (cfun->decl))
1190 emit_jump_insn (gen_interrupt_return ());
1191 else
1192 emit_jump_insn (gen_rl78_return ());
1195 /* Likewise, for exception handlers. */
1196 void
1197 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1199 /* FIXME - replace this with an indirect jump with stack adjust. */
1200 emit_jump_insn (gen_rl78_return ());
1203 #undef TARGET_ASM_FUNCTION_PROLOGUE
1204 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1206 /* We don't use this to actually emit the function prologue. We use
1207 this to insert a comment in the asm file describing the
1208 function. */
1209 static void
1210 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1212 int i;
1214 if (cfun->machine->framesize == 0)
1215 return;
1216 fprintf (file, "\t; start of function\n");
1218 if (cfun->machine->framesize_regs)
1220 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1221 for (i = 0; i < 16; i ++)
1222 if (cfun->machine->need_to_push[i])
1223 fprintf (file, " %s", word_regnames[i*2]);
1224 fprintf (file, "\n");
1227 if (frame_pointer_needed)
1228 fprintf (file, "\t; $fp points here (r22)\n");
1230 if (cfun->machine->framesize_locals)
1231 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1232 cfun->machine->framesize_locals == 1 ? "" : "s");
1234 if (cfun->machine->framesize_outgoing)
1235 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1236 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1239 /* Return an RTL describing where a function return value of type RET_TYPE
1240 is held. */
1242 #undef TARGET_FUNCTION_VALUE
1243 #define TARGET_FUNCTION_VALUE rl78_function_value
1245 static rtx
1246 rl78_function_value (const_tree ret_type,
1247 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1248 bool outgoing ATTRIBUTE_UNUSED)
1250 machine_mode mode = TYPE_MODE (ret_type);
1252 return gen_rtx_REG (mode, 8);
1255 #undef TARGET_PROMOTE_FUNCTION_MODE
1256 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1258 static machine_mode
1259 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1260 machine_mode mode,
1261 int *punsignedp ATTRIBUTE_UNUSED,
1262 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1264 return mode;
1267 /* Return an RTL expression describing the register holding a function
1268 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1269 be passed on the stack. CUM describes the previous parameters to the
1270 function and NAMED is false if the parameter is part of a variable
1271 parameter list, or the last named parameter before the start of a
1272 variable parameter list. */
1274 #undef TARGET_FUNCTION_ARG
1275 #define TARGET_FUNCTION_ARG rl78_function_arg
1277 static rtx
1278 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1279 machine_mode mode ATTRIBUTE_UNUSED,
1280 const_tree type ATTRIBUTE_UNUSED,
1281 bool named ATTRIBUTE_UNUSED)
1283 return NULL_RTX;
1286 #undef TARGET_FUNCTION_ARG_ADVANCE
1287 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1289 static void
1290 rl78_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type,
1291 bool named ATTRIBUTE_UNUSED)
1293 int rounded_size;
1294 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1296 rounded_size = ((mode == BLKmode)
1297 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1298 if (rounded_size & 1)
1299 rounded_size ++;
1300 (*cum) += rounded_size;
1303 #undef TARGET_FUNCTION_ARG_BOUNDARY
1304 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1306 static unsigned int
1307 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
1308 const_tree type ATTRIBUTE_UNUSED)
1310 return 16;
1313 /* Supported modifier letters:
1315 A - address of a MEM
1316 S - SADDR form of a real register
1317 v - real register corresponding to a virtual register
1318 m - minus - negative of CONST_INT value.
1319 C - inverse of a conditional (NE vs EQ for example)
1320 C - complement of an integer
1321 z - collapsed conditional
1322 s - shift count mod 8
1323 S - shift count mod 16
1324 r - reverse shift count (8-(count mod 8))
1325 B - bit position
1327 h - bottom HI of an SI
1328 H - top HI of an SI
1329 q - bottom QI of an HI
1330 Q - top QI of an HI
1331 e - third QI of an SI (i.e. where the ES register gets values from)
1332 E - fourth QI of an SI (i.e. MSB)
1336 /* Implements the bulk of rl78_print_operand, below. We do it this
1337 way because we need to test for a constant at the top level and
1338 insert the '#', but not test for it anywhere else as we recurse
1339 down into the operand. */
1340 static void
1341 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1343 int need_paren;
1345 switch (GET_CODE (op))
1347 case MEM:
1348 if (letter == 'A')
1349 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1350 else
1352 if (rl78_far_p (op))
1354 fprintf (file, "es:");
1355 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1357 if (letter == 'H')
1359 op = adjust_address (op, HImode, 2);
1360 letter = 0;
1362 if (letter == 'h')
1364 op = adjust_address (op, HImode, 0);
1365 letter = 0;
1367 if (letter == 'Q')
1369 op = adjust_address (op, QImode, 1);
1370 letter = 0;
1372 if (letter == 'q')
1374 op = adjust_address (op, QImode, 0);
1375 letter = 0;
1377 if (letter == 'e')
1379 op = adjust_address (op, QImode, 2);
1380 letter = 0;
1382 if (letter == 'E')
1384 op = adjust_address (op, QImode, 3);
1385 letter = 0;
1387 if (CONSTANT_P (XEXP (op, 0)))
1389 fprintf (file, "!");
1390 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1392 else if (GET_CODE (XEXP (op, 0)) == PLUS
1393 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1395 fprintf (file, "!");
1396 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1398 else if (GET_CODE (XEXP (op, 0)) == PLUS
1399 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1400 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1402 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1403 fprintf (file, "[");
1404 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1405 fprintf (file, "]");
1407 else
1409 fprintf (file, "[");
1410 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1411 fprintf (file, "]");
1414 break;
1416 case REG:
1417 if (letter == 'Q')
1418 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1419 else if (letter == 'H')
1420 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1421 else if (letter == 'q')
1422 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1423 else if (letter == 'e')
1424 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1425 else if (letter == 'E')
1426 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1427 else if (letter == 'S')
1428 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1429 else if (GET_MODE (op) == HImode
1430 && ! (REGNO (op) & ~0xfe))
1432 if (letter == 'v')
1433 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1434 else
1435 fprintf (file, "%s", word_regnames [REGNO (op)]);
1437 else
1438 fprintf (file, "%s", reg_names [REGNO (op)]);
1439 break;
1441 case CONST_INT:
1442 if (letter == 'Q')
1443 fprintf (file, "%ld", INTVAL (op) >> 8);
1444 else if (letter == 'H')
1445 fprintf (file, "%ld", INTVAL (op) >> 16);
1446 else if (letter == 'q')
1447 fprintf (file, "%ld", INTVAL (op) & 0xff);
1448 else if (letter == 'h')
1449 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1450 else if (letter == 'e')
1451 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1452 else if (letter == 'B')
1453 fprintf (file, "%d", exact_log2 (INTVAL (op)));
1454 else if (letter == 'E')
1455 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1456 else if (letter == 'm')
1457 fprintf (file, "%ld", - INTVAL (op));
1458 else if (letter == 's')
1459 fprintf (file, "%ld", INTVAL (op) % 8);
1460 else if (letter == 'S')
1461 fprintf (file, "%ld", INTVAL (op) % 16);
1462 else if (letter == 'r')
1463 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1464 else if (letter == 'C')
1465 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1466 else
1467 fprintf (file, "%ld", INTVAL (op));
1468 break;
1470 case CONST:
1471 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1472 break;
1474 case ZERO_EXTRACT:
1476 int bits = INTVAL (XEXP (op, 1));
1477 int ofs = INTVAL (XEXP (op, 2));
1478 if (bits == 16 && ofs == 0)
1479 fprintf (file, "%%lo16(");
1480 else if (bits == 16 && ofs == 16)
1481 fprintf (file, "%%hi16(");
1482 else if (bits == 8 && ofs == 16)
1483 fprintf (file, "%%hi8(");
1484 else
1485 gcc_unreachable ();
1486 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1487 fprintf (file, ")");
1489 break;
1491 case ZERO_EXTEND:
1492 if (GET_CODE (XEXP (op, 0)) == REG)
1493 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1494 else
1495 print_rtl (file, op);
1496 break;
1498 case PLUS:
1499 need_paren = 0;
1500 if (letter == 'H')
1502 fprintf (file, "%%hi16(");
1503 need_paren = 1;
1504 letter = 0;
1506 if (letter == 'h')
1508 fprintf (file, "%%lo16(");
1509 need_paren = 1;
1510 letter = 0;
1512 if (letter == 'e')
1514 fprintf (file, "%%hi8(");
1515 need_paren = 1;
1516 letter = 0;
1518 if (letter == 'q' || letter == 'Q')
1519 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1521 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1523 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1524 fprintf (file, "+");
1525 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1527 else
1529 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1530 fprintf (file, "+");
1531 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1533 if (need_paren)
1534 fprintf (file, ")");
1535 break;
1537 case SYMBOL_REF:
1538 need_paren = 0;
1539 if (letter == 'H')
1541 fprintf (file, "%%hi16(");
1542 need_paren = 1;
1543 letter = 0;
1545 if (letter == 'h')
1547 fprintf (file, "%%lo16(");
1548 need_paren = 1;
1549 letter = 0;
1551 if (letter == 'e')
1553 fprintf (file, "%%hi8(");
1554 need_paren = 1;
1555 letter = 0;
1557 if (letter == 'q' || letter == 'Q')
1558 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1560 output_addr_const (file, op);
1561 if (need_paren)
1562 fprintf (file, ")");
1563 break;
1565 case CODE_LABEL:
1566 case LABEL_REF:
1567 output_asm_label (op);
1568 break;
1570 case LTU:
1571 if (letter == 'z')
1572 fprintf (file, "#comparison eliminated");
1573 else
1574 fprintf (file, letter == 'C' ? "nc" : "c");
1575 break;
1576 case LEU:
1577 if (letter == 'z')
1578 fprintf (file, "br");
1579 else
1580 fprintf (file, letter == 'C' ? "h" : "nh");
1581 break;
1582 case GEU:
1583 if (letter == 'z')
1584 fprintf (file, "br");
1585 else
1586 fprintf (file, letter == 'C' ? "c" : "nc");
1587 break;
1588 case GTU:
1589 if (letter == 'z')
1590 fprintf (file, "#comparison eliminated");
1591 else
1592 fprintf (file, letter == 'C' ? "nh" : "h");
1593 break;
1594 case EQ:
1595 if (letter == 'z')
1596 fprintf (file, "br");
1597 else
1598 fprintf (file, letter == 'C' ? "nz" : "z");
1599 break;
1600 case NE:
1601 if (letter == 'z')
1602 fprintf (file, "#comparison eliminated");
1603 else
1604 fprintf (file, letter == 'C' ? "z" : "nz");
1605 break;
1607 /* Note: these assume appropriate adjustments were made so that
1608 unsigned comparisons, which is all this chip has, will
1609 work. */
1610 case LT:
1611 if (letter == 'z')
1612 fprintf (file, "#comparison eliminated");
1613 else
1614 fprintf (file, letter == 'C' ? "nc" : "c");
1615 break;
1616 case LE:
1617 if (letter == 'z')
1618 fprintf (file, "br");
1619 else
1620 fprintf (file, letter == 'C' ? "h" : "nh");
1621 break;
1622 case GE:
1623 if (letter == 'z')
1624 fprintf (file, "br");
1625 else
1626 fprintf (file, letter == 'C' ? "c" : "nc");
1627 break;
1628 case GT:
1629 if (letter == 'z')
1630 fprintf (file, "#comparison eliminated");
1631 else
1632 fprintf (file, letter == 'C' ? "nh" : "h");
1633 break;
1635 default:
1636 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1637 break;
1641 #undef TARGET_PRINT_OPERAND
1642 #define TARGET_PRINT_OPERAND rl78_print_operand
1644 static void
1645 rl78_print_operand (FILE * file, rtx op, int letter)
1647 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S' && letter != 'B')
1648 fprintf (file, "#");
1649 rl78_print_operand_1 (file, op, letter);
1652 #undef TARGET_TRAMPOLINE_INIT
1653 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1655 /* Note that the RL78's addressing makes it very difficult to do
1656 trampolines on the stack. So, libgcc has a small pool of
1657 trampolines from which one is allocated to this task. */
1658 static void
1659 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1661 rtx mov_addr, thunk_addr;
1662 rtx function = XEXP (DECL_RTL (fndecl), 0);
1664 mov_addr = adjust_address (m_tramp, HImode, 0);
1665 thunk_addr = gen_reg_rtx (HImode);
1667 function = force_reg (HImode, function);
1668 static_chain = force_reg (HImode, static_chain);
1670 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1671 emit_move_insn (mov_addr, thunk_addr);
1673 cfun->machine->trampolines_used = 1;
1676 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1677 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1679 static rtx
1680 rl78_trampoline_adjust_address (rtx m_tramp)
1682 rtx x = gen_rtx_MEM (HImode, m_tramp);
1683 return x;
1686 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1687 the "normal" compares, specifically, it only has unsigned compares,
1688 so we must synthesize the missing ones. */
1689 void
1690 rl78_expand_compare (rtx *operands)
1692 if (GET_CODE (operands[2]) == MEM)
1693 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1698 /* Define this to 1 if you are debugging the peephole optimizers. */
1699 #define DEBUG_PEEP 0
1701 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1702 The default "word" size is a byte so we can effectively use all the
1703 registers, but we want to do 16-bit moves whenever possible. This
1704 function determines when such a move is an option. */
1705 bool
1706 rl78_peep_movhi_p (rtx *operands)
1708 int i;
1709 rtx m, a;
1711 /* (set (op0) (op1))
1712 (set (op2) (op3)) */
1714 if (! rl78_virt_insns_ok ())
1715 return false;
1717 #if DEBUG_PEEP
1718 fprintf (stderr, "\033[33m");
1719 debug_rtx (operands[0]);
1720 debug_rtx (operands[1]);
1721 debug_rtx (operands[2]);
1722 debug_rtx (operands[3]);
1723 fprintf (stderr, "\033[0m");
1724 #endif
1726 /* You can move a constant to memory as QImode, but not HImode. */
1727 if (GET_CODE (operands[0]) == MEM
1728 && GET_CODE (operands[1]) != REG)
1730 #if DEBUG_PEEP
1731 fprintf (stderr, "no peep: move constant to memory\n");
1732 #endif
1733 return false;
1736 if (rtx_equal_p (operands[0], operands[3]))
1738 #if DEBUG_PEEP
1739 fprintf (stderr, "no peep: overlapping\n");
1740 #endif
1741 return false;
1744 for (i = 0; i < 2; i ++)
1746 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1748 #if DEBUG_PEEP
1749 fprintf (stderr, "no peep: different codes\n");
1750 #endif
1751 return false;
1753 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1755 #if DEBUG_PEEP
1756 fprintf (stderr, "no peep: different modes\n");
1757 #endif
1758 return false;
1761 switch (GET_CODE (operands[i]))
1763 case REG:
1764 /* LSB MSB */
1765 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1766 || GET_MODE (operands[i]) != QImode)
1768 #if DEBUG_PEEP
1769 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1770 REGNO (operands[i]), REGNO (operands[i+2]),
1772 #endif
1773 return false;
1775 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1777 #if DEBUG_PEEP
1778 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1779 #endif
1780 return false;
1782 break;
1784 case CONST_INT:
1785 break;
1787 case MEM:
1788 if (GET_MODE (operands[i]) != QImode)
1789 return false;
1790 if (MEM_ALIGN (operands[i]) < 16)
1791 return false;
1792 a = XEXP (operands[i], 0);
1793 if (GET_CODE (a) == CONST)
1794 a = XEXP (a, 0);
1795 if (GET_CODE (a) == PLUS)
1796 a = XEXP (a, 1);
1797 if (GET_CODE (a) == CONST_INT
1798 && INTVAL (a) & 1)
1800 #if DEBUG_PEEP
1801 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1802 debug_rtx (operands[i]);
1803 #endif
1804 return false;
1806 m = adjust_address (operands[i], QImode, 1);
1807 if (! rtx_equal_p (m, operands[i+2]))
1809 #if DEBUG_PEEP
1810 fprintf (stderr, "no peep: wrong mem %d\n", i);
1811 debug_rtx (m);
1812 debug_rtx (operands[i+2]);
1813 #endif
1814 return false;
1816 break;
1818 default:
1819 #if DEBUG_PEEP
1820 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1821 #endif
1822 return false;
1825 #if DEBUG_PEEP
1826 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1827 #endif
1828 return true;
1831 /* Likewise, when a peephole is activated, this function helps compute
1832 the new operands. */
1833 void
1834 rl78_setup_peep_movhi (rtx *operands)
1836 int i;
1838 for (i = 0; i < 2; i ++)
1840 switch (GET_CODE (operands[i]))
1842 case REG:
1843 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1844 break;
1846 case CONST_INT:
1847 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char) INTVAL (operands[i+2])) * 256);
1848 break;
1850 case MEM:
1851 operands[i+4] = adjust_address (operands[i], HImode, 0);
1852 break;
1854 default:
1855 break;
1861 How Devirtualization works in the RL78 GCC port
1863 Background
1865 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1866 bytes of register space, in four banks, memory-mapped. One bank is
1867 the "selected" bank and holds the registers used for primary
1868 operations. Since the registers are memory mapped, often you can
1869 still refer to the unselected banks via memory accesses.
1871 Virtual Registers
1873 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1874 and refers to the other banks via their memory addresses, although
1875 they're treated as regular registers internally. These "virtual"
1876 registers are R8 through R23 (bank3 is reserved for asm-based
1877 interrupt handlers).
1879 There are four machine description files:
1881 rl78.md - common register-independent patterns and definitions
1882 rl78-expand.md - expanders
1883 rl78-virt.md - patterns that match BEFORE devirtualization
1884 rl78-real.md - patterns that match AFTER devirtualization
1886 At least through register allocation and reload, gcc is told that it
1887 can do pretty much anything - but may only use the virtual registers.
1888 GCC cannot properly create the varying addressing modes that the RL78
1889 supports in an efficient way.
1891 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1892 uses the "valloc" attribute in rl78-virt.md for determining the rules
1893 by which it will replace virtual registers with real registers (or
1894 not) and how to make up addressing modes. For example, insns tagged
1895 with "ro1" have a single read-only parameter, which may need to be
1896 moved from memory/constant/vreg to a suitable real register. As part
1897 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1898 patterns and enabling the rl78-real.md patterns. The new patterns'
1899 constraints are used to determine the real registers used. NOTE:
1900 patterns in rl78-virt.md essentially ignore the constrains and rely on
1901 predicates, where the rl78-real.md ones essentially ignore the
1902 predicates and rely on the constraints.
1904 The devirtualization pass is scheduled via the pass manager (despite
1905 being called "rl78_reorg") so it can be scheduled prior to var-track
1906 (the idea is to let gdb know about the new registers). Ideally, it
1907 would be scheduled right after pro/epilogue generation, so the
1908 post-reload optimizers could operate on the real registers, but when I
1909 tried that there were some issues building the target libraries.
1911 During devirtualization, a simple register move optimizer is run. It
1912 would be better to run a full CSE/propogation pass on it though, but
1913 that has not yet been attempted.
1916 #define DEBUG_ALLOC 0
1918 #define OP(x) (*recog_data.operand_loc[x])
1920 /* This array is used to hold knowledge about the contents of the
1921 real registers (A ... H), the memory-based registers (r8 ... r31)
1922 and the first NUM_STACK_LOCS words on the stack. We use this to
1923 avoid generating redundant move instructions.
1925 A value in the range 0 .. 31 indicates register A .. r31.
1926 A value in the range 32 .. 63 indicates stack slot (value - 32).
1927 A value of NOT_KNOWN indicates that the contents of that location
1928 are not known. */
1930 #define NUM_STACK_LOCS 32
1931 #define NOT_KNOWN 127
1933 static unsigned char content_memory [32 + NUM_STACK_LOCS];
1935 static unsigned char saved_update_index = NOT_KNOWN;
1936 static unsigned char saved_update_value;
1937 static machine_mode saved_update_mode;
1940 static inline void
1941 clear_content_memory (void)
1943 memset (content_memory, NOT_KNOWN, sizeof content_memory);
1944 if (dump_file)
1945 fprintf (dump_file, " clear content memory\n");
1946 saved_update_index = NOT_KNOWN;
1949 /* Convert LOC into an index into the content_memory array.
1950 If LOC cannot be converted, return NOT_KNOWN. */
1952 static unsigned char
1953 get_content_index (rtx loc)
1955 machine_mode mode;
1957 if (loc == NULL_RTX)
1958 return NOT_KNOWN;
1960 if (REG_P (loc))
1962 if (REGNO (loc) < 32)
1963 return REGNO (loc);
1964 return NOT_KNOWN;
1967 mode = GET_MODE (loc);
1969 if (! rl78_stack_based_mem (loc, mode))
1970 return NOT_KNOWN;
1972 loc = XEXP (loc, 0);
1974 if (REG_P (loc))
1975 /* loc = MEM (SP) */
1976 return 32;
1978 /* loc = MEM (PLUS (SP, INT)). */
1979 loc = XEXP (loc, 1);
1981 if (INTVAL (loc) < NUM_STACK_LOCS)
1982 return 32 + INTVAL (loc);
1984 return NOT_KNOWN;
1987 /* Return a string describing content INDEX in mode MODE.
1988 WARNING: Can return a pointer to a static buffer. */
1989 static const char *
1990 get_content_name (unsigned char index, machine_mode mode)
1992 static char buffer [128];
1994 if (index == NOT_KNOWN)
1995 return "Unknown";
1997 if (index > 31)
1998 sprintf (buffer, "stack slot %d", index - 32);
1999 else if (mode == HImode)
2000 sprintf (buffer, "%s%s",
2001 reg_names [index + 1], reg_names [index]);
2002 else
2003 return reg_names [index];
2005 return buffer;
2008 #if DEBUG_ALLOC
2010 static void
2011 display_content_memory (FILE * file)
2013 unsigned int i;
2015 fprintf (file, " Known memory contents:\n");
2017 for (i = 0; i < sizeof content_memory; i++)
2018 if (content_memory[i] != NOT_KNOWN)
2020 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
2021 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
2024 #endif
2026 static void
2027 update_content (unsigned char index, unsigned char val, machine_mode mode)
2029 unsigned int i;
2031 gcc_assert (index < sizeof content_memory);
2033 content_memory [index] = val;
2034 if (val != NOT_KNOWN)
2035 content_memory [val] = index;
2037 /* Make the entry in dump_file *before* VAL is increased below. */
2038 if (dump_file)
2040 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
2041 if (val == NOT_KNOWN)
2042 fprintf (dump_file, "Unknown\n");
2043 else
2044 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
2047 if (mode == HImode)
2049 val = val == NOT_KNOWN ? val : val + 1;
2051 content_memory [index + 1] = val;
2052 if (val != NOT_KNOWN)
2054 content_memory [val] = index + 1;
2055 -- val;
2059 /* Any other places that had INDEX recorded as their contents are now invalid. */
2060 for (i = 0; i < sizeof content_memory; i++)
2062 if (i == index
2063 || (val != NOT_KNOWN && i == val))
2065 if (mode == HImode)
2066 ++ i;
2067 continue;
2070 if (content_memory[i] == index
2071 || (val != NOT_KNOWN && content_memory[i] == val))
2073 content_memory[i] = NOT_KNOWN;
2075 if (dump_file)
2076 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2078 if (mode == HImode)
2079 content_memory[++ i] = NOT_KNOWN;
2084 /* Record that LOC contains VALUE.
2085 For HImode locations record that LOC+1 contains VALUE+1.
2086 If LOC is not a register or stack slot, do nothing.
2087 If VALUE is not a register or stack slot, clear the recorded content. */
2089 static void
2090 record_content (rtx loc, rtx value)
2092 machine_mode mode;
2093 unsigned char index;
2094 unsigned char val;
2096 if ((index = get_content_index (loc)) == NOT_KNOWN)
2097 return;
2099 val = get_content_index (value);
2101 mode = GET_MODE (loc);
2103 if (val == index)
2105 if (! optimize)
2106 return;
2108 /* This should not happen when optimizing. */
2109 #if 1
2110 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2111 get_content_name (val, mode));
2112 return;
2113 #else
2114 gcc_unreachable ();
2115 #endif
2118 update_content (index, val, mode);
2121 /* Returns TRUE if LOC already contains a copy of VALUE. */
2123 static bool
2124 already_contains (rtx loc, rtx value)
2126 unsigned char index;
2127 unsigned char val;
2129 if ((index = get_content_index (loc)) == NOT_KNOWN)
2130 return false;
2132 if ((val = get_content_index (value)) == NOT_KNOWN)
2133 return false;
2135 if (content_memory [index] != val)
2136 return false;
2138 if (GET_MODE (loc) == HImode)
2139 return content_memory [index + 1] == val + 1;
2141 return true;
2144 bool
2145 rl78_es_addr (rtx addr)
2147 if (GET_CODE (addr) == MEM)
2148 addr = XEXP (addr, 0);
2149 if (GET_CODE (addr) != UNSPEC)
2150 return false;
2151 if (XINT (addr, 1) != UNS_ES_ADDR)
2152 return false;
2153 return true;
2157 rl78_es_base (rtx addr)
2159 if (GET_CODE (addr) == MEM)
2160 addr = XEXP (addr, 0);
2161 addr = XVECEXP (addr, 0, 1);
2162 if (GET_CODE (addr) == CONST
2163 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2164 addr = XEXP (XEXP (addr, 0), 0);
2165 /* Mode doesn't matter here. */
2166 return gen_rtx_MEM (HImode, addr);
2169 /* Rescans an insn to see if it's recognized again. This is done
2170 carefully to ensure that all the constraint information is accurate
2171 for the newly matched insn. */
2172 static bool
2173 insn_ok_now (rtx_insn *insn)
2175 rtx pattern = PATTERN (insn);
2176 int i;
2178 INSN_CODE (insn) = -1;
2180 if (recog (pattern, insn, 0) > -1)
2182 extract_insn (insn);
2183 if (constrain_operands (1, get_preferred_alternatives (insn)))
2185 #if DEBUG_ALLOC
2186 fprintf (stderr, "\033[32m");
2187 debug_rtx (insn);
2188 fprintf (stderr, "\033[0m");
2189 #endif
2190 if (SET_P (pattern))
2191 record_content (SET_DEST (pattern), SET_SRC (pattern));
2193 /* We need to detect far addresses that haven't been
2194 converted to es/lo16 format. */
2195 for (i=0; i<recog_data.n_operands; i++)
2196 if (GET_CODE (OP (i)) == MEM
2197 && GET_MODE (XEXP (OP (i), 0)) == SImode
2198 && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
2199 return false;
2201 return true;
2204 else
2206 /* We need to re-recog the insn with virtual registers to get
2207 the operands. */
2208 cfun->machine->virt_insns_ok = 1;
2209 if (recog (pattern, insn, 0) > -1)
2211 extract_insn (insn);
2212 if (constrain_operands (0, get_preferred_alternatives (insn)))
2214 cfun->machine->virt_insns_ok = 0;
2215 return false;
2219 #if DEBUG_ALLOC
2220 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2221 debug_rtx (insn);
2222 #endif
2223 gcc_unreachable ();
2226 #if DEBUG_ALLOC
2227 fprintf (stderr, "\033[31m");
2228 debug_rtx (insn);
2229 fprintf (stderr, "\033[0m");
2230 #endif
2231 return false;
2234 #if DEBUG_ALLOC
2235 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2236 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2237 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2238 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2239 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2240 #else
2241 #define FAILED gcc_unreachable ()
2242 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2243 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2244 #endif
2246 /* Registers into which we move the contents of virtual registers. */
2247 #define X gen_rtx_REG (QImode, X_REG)
2248 #define A gen_rtx_REG (QImode, A_REG)
2249 #define C gen_rtx_REG (QImode, C_REG)
2250 #define B gen_rtx_REG (QImode, B_REG)
2251 #define E gen_rtx_REG (QImode, E_REG)
2252 #define D gen_rtx_REG (QImode, D_REG)
2253 #define L gen_rtx_REG (QImode, L_REG)
2254 #define H gen_rtx_REG (QImode, H_REG)
2256 #define AX gen_rtx_REG (HImode, AX_REG)
2257 #define BC gen_rtx_REG (HImode, BC_REG)
2258 #define DE gen_rtx_REG (HImode, DE_REG)
2259 #define HL gen_rtx_REG (HImode, HL_REG)
2261 /* Returns TRUE if R is a virtual register. */
2262 static inline bool
2263 is_virtual_register (rtx r)
2265 return (GET_CODE (r) == REG
2266 && REGNO (r) >= 8
2267 && REGNO (r) < 32);
2270 /* In all these alloc routines, we expect the following: the insn
2271 pattern is unshared, the insn was previously recognized and failed
2272 due to predicates or constraints, and the operand data is in
2273 recog_data. */
2275 static int virt_insn_was_frame;
2277 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2278 needed. */
2279 static rtx
2280 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2282 #if DEBUG_ALLOC
2283 fprintf (stderr, "\033[36m%d: ", line);
2284 debug_rtx (r);
2285 fprintf (stderr, "\033[0m");
2286 #endif
2287 /*SCHED_GROUP_P (r) = 1;*/
2288 if (virt_insn_was_frame)
2289 RTX_FRAME_RELATED_P (r) = 1;
2290 return r;
2293 #define EM(x) EM2 (__LINE__, x)
2295 /* Return a suitable RTX for the low half of a __far address. */
2296 static rtx
2297 rl78_lo16 (rtx addr)
2299 rtx r;
2301 if (GET_CODE (addr) == SYMBOL_REF
2302 || GET_CODE (addr) == CONST)
2304 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2305 r = gen_rtx_CONST (HImode, r);
2307 else
2308 r = rl78_subreg (HImode, addr, SImode, 0);
2310 r = gen_es_addr (r);
2312 return r;
2315 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2316 static rtx
2317 rl78_hi8 (rtx addr)
2319 if (GET_CODE (addr) == SYMBOL_REF
2320 || GET_CODE (addr) == CONST)
2322 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2323 r = gen_rtx_CONST (QImode, r);
2324 return r;
2326 return rl78_subreg (QImode, addr, SImode, 2);
2329 static void
2330 add_postponed_content_update (rtx to, rtx value)
2332 unsigned char index;
2334 if ((index = get_content_index (to)) == NOT_KNOWN)
2335 return;
2337 gcc_assert (saved_update_index == NOT_KNOWN);
2338 saved_update_index = index;
2339 saved_update_value = get_content_index (value);
2340 saved_update_mode = GET_MODE (to);
2343 static void
2344 process_postponed_content_update (void)
2346 if (saved_update_index != NOT_KNOWN)
2348 update_content (saved_update_index, saved_update_value, saved_update_mode);
2349 saved_update_index = NOT_KNOWN;
2353 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2354 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2355 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2356 BEFORE is true, FROM otherwise. */
2357 static rtx
2358 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2360 machine_mode mode = GET_MODE (to);
2362 if (optimize && before && already_contains (to, from))
2364 #if DEBUG_ALLOC
2365 display_content_memory (stderr);
2366 #endif
2367 if (dump_file)
2369 fprintf (dump_file, " Omit move of %s into ",
2370 get_content_name (get_content_index (from), mode));
2371 fprintf (dump_file, "%s as it already contains this value\n",
2372 get_content_name (get_content_index (to), mode));
2375 else
2377 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2379 EM (move);
2381 if (where == NULL_RTX)
2382 emit_insn (move);
2383 else if (before)
2384 emit_insn_before (move, where);
2385 else
2387 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2389 /* If necessary move REG_EH_REGION notes forward.
2390 cf. compiling gcc.dg/pr44545.c. */
2391 if (note != NULL_RTX)
2393 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2394 remove_note (where, note);
2397 emit_insn_after (move, where);
2400 if (before)
2401 record_content (to, from);
2402 else
2403 add_postponed_content_update (to, from);
2406 return before ? to : from;
2409 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2410 copy it into NEWBASE and return the updated MEM. Otherwise just
2411 return M. Any needed insns are emitted before BEFORE. */
2412 static rtx
2413 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2415 rtx base, index, addendr;
2416 int addend = 0;
2417 int need_es = 0;
2419 if (! MEM_P (m))
2420 return m;
2422 if (GET_MODE (XEXP (m, 0)) == SImode)
2424 rtx new_m;
2425 rtx seg = rl78_hi8 (XEXP (m, 0));
2427 #if DEBUG_ALLOC
2428 fprintf (stderr, "setting ES:\n");
2429 debug_rtx(seg);
2430 #endif
2431 emit_insn_before (EM (gen_movqi (A, seg)), before);
2432 emit_insn_before (EM (gen_movqi_es (A)), before);
2433 record_content (A, NULL_RTX);
2435 new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2436 MEM_COPY_ATTRIBUTES (new_m, m);
2437 m = new_m;
2438 need_es = 1;
2441 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2442 gcc_assert (index == NULL_RTX);
2444 #if DEBUG_ALLOC
2445 fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m");
2446 debug_rtx (base);
2447 #endif
2448 if (base == NULL_RTX)
2449 return m;
2451 if (addendr && GET_CODE (addendr) == CONST_INT)
2452 addend = INTVAL (addendr);
2454 gcc_assert (REG_P (base));
2455 gcc_assert (REG_P (newbase));
2457 if (REGNO (base) == SP_REG)
2459 if (addend >= 0 && addend <= 255)
2460 return m;
2463 /* BASE should be a virtual register. We copy it to NEWBASE. If
2464 the addend is out of range for DE/HL, we use AX to compute the full
2465 address. */
2467 if (addend < 0
2468 || (addend > 255 && REGNO (newbase) != 2)
2469 || (addendr && GET_CODE (addendr) != CONST_INT))
2471 /* mov ax, vreg
2472 add ax, #imm
2473 mov hl, ax */
2474 EM (emit_insn_before (gen_movhi (AX, base), before));
2475 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2476 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2477 record_content (AX, NULL_RTX);
2478 record_content (newbase, NULL_RTX);
2480 base = newbase;
2481 addend = 0;
2483 else
2485 base = gen_and_emit_move (newbase, base, before, true);
2488 if (addend)
2490 record_content (base, NULL_RTX);
2491 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2494 #if DEBUG_ALLOC
2495 fprintf (stderr, "\033[33m");
2496 debug_rtx (m);
2497 #endif
2498 if (need_es)
2499 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2500 else
2501 m = change_address (m, GET_MODE (m), base);
2502 #if DEBUG_ALLOC
2503 debug_rtx (m);
2504 fprintf (stderr, "\033[0m");
2505 #endif
2506 return m;
2509 /* Copy SRC to accumulator (A or AX), placing any generated insns
2510 before BEFORE. Returns accumulator RTX. */
2511 static rtx
2512 move_to_acc (int opno, rtx before)
2514 rtx src = OP (opno);
2515 machine_mode mode = GET_MODE (src);
2517 if (REG_P (src) && REGNO (src) < 2)
2518 return src;
2520 if (mode == VOIDmode)
2521 mode = recog_data.operand_mode[opno];
2523 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2526 static void
2527 force_into_acc (rtx src, rtx before)
2529 machine_mode mode = GET_MODE (src);
2530 rtx move;
2532 if (REG_P (src) && REGNO (src) < 2)
2533 return;
2535 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2537 EM (move);
2539 emit_insn_before (move, before);
2540 record_content (AX, NULL_RTX);
2543 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2544 after AFTER. Returns accumulator RTX. */
2545 static rtx
2546 move_from_acc (unsigned int opno, rtx after)
2548 rtx dest = OP (opno);
2549 machine_mode mode = GET_MODE (dest);
2551 if (REG_P (dest) && REGNO (dest) < 2)
2552 return dest;
2554 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2557 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2558 before BEFORE. Returns reg RTX. */
2559 static rtx
2560 move_acc_to_reg (rtx acc, int regno, rtx before)
2562 machine_mode mode = GET_MODE (acc);
2563 rtx reg;
2565 reg = gen_rtx_REG (mode, regno);
2567 return gen_and_emit_move (reg, acc, before, true);
2570 /* Copy SRC to X, placing any generated insns before BEFORE.
2571 Returns X RTX. */
2572 static rtx
2573 move_to_x (int opno, rtx before)
2575 rtx src = OP (opno);
2576 machine_mode mode = GET_MODE (src);
2577 rtx reg;
2579 if (mode == VOIDmode)
2580 mode = recog_data.operand_mode[opno];
2581 reg = (mode == QImode) ? X : AX;
2583 if (mode == QImode || ! is_virtual_register (OP (opno)))
2585 OP (opno) = move_to_acc (opno, before);
2586 OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
2587 return reg;
2590 return gen_and_emit_move (reg, src, before, true);
2593 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2594 Returns H/HL RTX. */
2595 static rtx
2596 move_to_hl (int opno, rtx before)
2598 rtx src = OP (opno);
2599 machine_mode mode = GET_MODE (src);
2600 rtx reg;
2602 if (mode == VOIDmode)
2603 mode = recog_data.operand_mode[opno];
2604 reg = (mode == QImode) ? L : HL;
2606 if (mode == QImode || ! is_virtual_register (OP (opno)))
2608 OP (opno) = move_to_acc (opno, before);
2609 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2610 return reg;
2613 return gen_and_emit_move (reg, src, before, true);
2616 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2617 Returns E/DE RTX. */
2618 static rtx
2619 move_to_de (int opno, rtx before)
2621 rtx src = OP (opno);
2622 machine_mode mode = GET_MODE (src);
2623 rtx reg;
2625 if (mode == VOIDmode)
2626 mode = recog_data.operand_mode[opno];
2628 reg = (mode == QImode) ? E : DE;
2630 if (mode == QImode || ! is_virtual_register (OP (opno)))
2632 OP (opno) = move_to_acc (opno, before);
2633 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2635 else
2637 gen_and_emit_move (reg, src, before, true);
2640 return reg;
2643 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2644 static void
2645 rl78_alloc_physical_registers_op1 (rtx_insn *insn)
2647 /* op[0] = func op[1] */
2649 /* We first try using A as the destination, then copying it
2650 back. */
2651 if (rtx_equal_p (OP (0), OP (1)))
2653 OP (0) =
2654 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2656 else
2658 /* If necessary, load the operands into BC and HL.
2659 Check to see if we already have OP (0) in HL
2660 and if so, swap the order. */
2661 if (MEM_P (OP (0))
2662 && already_contains (HL, XEXP (OP (0), 0)))
2664 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2665 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2667 else
2669 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2670 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2674 MAYBE_OK (insn);
2676 OP (0) = move_from_acc (0, insn);
2678 MAYBE_OK (insn);
2680 /* Try copying the src to acc first, then. This is for, for
2681 example, ZERO_EXTEND or NOT. */
2682 OP (1) = move_to_acc (1, insn);
2684 MUST_BE_OK (insn);
2687 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2688 Assumes that the current insn has already been recognised and hence the
2689 constraint data has been filled in. */
2690 static bool
2691 has_constraint (unsigned int opnum, enum constraint_num constraint)
2693 const char * p = recog_data.constraints[opnum];
2695 /* No constraints means anything is accepted. */
2696 if (p == NULL || *p == 0 || *p == ',')
2697 return true;
2701 char c;
2702 unsigned int len;
2704 c = *p;
2705 len = CONSTRAINT_LEN (c, p);
2706 gcc_assert (len > 0);
2708 switch (c)
2710 case 0:
2711 case ',':
2712 return false;
2713 default:
2714 if (lookup_constraint (p) == constraint)
2715 return true;
2717 p += len;
2719 while (1);
2722 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2723 static void
2724 rl78_alloc_physical_registers_op2 (rtx_insn *insn)
2726 rtx prev;
2727 rtx first;
2728 bool hl_used;
2729 int tmp_id;
2730 rtx saved_op1;
2732 if (rtx_equal_p (OP (0), OP (1)))
2734 OP (0) =
2735 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2736 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2738 else if (rtx_equal_p (OP (0), OP (2)))
2740 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2741 OP (0) =
2742 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2744 else
2746 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2747 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2748 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2751 MAYBE_OK (insn);
2753 prev = prev_nonnote_nondebug_insn (insn);
2754 if (recog_data.constraints[1][0] == '%'
2755 && is_virtual_register (OP (1))
2756 && ! is_virtual_register (OP (2))
2757 && ! CONSTANT_P (OP (2)))
2759 rtx tmp = OP (1);
2760 OP (1) = OP (2);
2761 OP (2) = tmp;
2764 /* Make a note of whether (H)L is being used. It matters
2765 because if OP (2) also needs reloading, then we must take
2766 care not to corrupt HL. */
2767 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2769 /* If HL is not currently being used and dest == op1 then there are
2770 some possible optimizations available by reloading one of the
2771 operands into HL, before trying to use the accumulator. */
2772 if (optimize
2773 && ! hl_used
2774 && rtx_equal_p (OP (0), OP (1)))
2776 /* If op0 is a Ws1 type memory address then switching the base
2777 address register to HL might allow us to perform an in-memory
2778 operation. (eg for the INCW instruction).
2780 FIXME: Adding the move into HL is costly if this optimization is not
2781 going to work, so for now, make sure that we know that the new insn will
2782 match the requirements of the addhi3_real pattern. Really we ought to
2783 generate a candidate sequence, test that, and then install it if the
2784 results are good. */
2785 if (satisfies_constraint_Ws1 (OP (0))
2786 && has_constraint (0, CONSTRAINT_Wh1)
2787 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2789 rtx base, index, addend, newbase;
2791 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
2792 gcc_assert (index == NULL_RTX);
2793 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2795 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2796 if (addend != NULL_RTX)
2798 newbase = gen_and_emit_move (HL, base, insn, true);
2799 record_content (newbase, NULL_RTX);
2800 newbase = gen_rtx_PLUS (HImode, newbase, addend);
2802 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
2804 /* We do not want to fail here as this means that
2805 we have inserted useless insns into the stream. */
2806 MUST_BE_OK (insn);
2809 else if (REG_P (OP (0))
2810 && satisfies_constraint_Ws1 (OP (2))
2811 && has_constraint (2, CONSTRAINT_Wh1))
2813 rtx base, index, addend, newbase;
2815 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
2816 gcc_assert (index == NULL_RTX);
2817 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2819 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2820 if (addend != NULL_RTX)
2822 gen_and_emit_move (HL, base, insn, true);
2824 if (REGNO (OP (0)) != X_REG)
2826 OP (1) = move_to_acc (1, insn);
2827 OP (0) = move_from_acc (0, insn);
2830 record_content (HL, NULL_RTX);
2831 newbase = gen_rtx_PLUS (HImode, HL, addend);
2833 OP (2) = change_address (OP (2), VOIDmode, newbase);
2835 /* We do not want to fail here as this means that
2836 we have inserted useless insns into the stream. */
2837 MUST_BE_OK (insn);
2842 OP (0) = move_from_acc (0, insn);
2844 tmp_id = get_max_insn_count ();
2845 saved_op1 = OP (1);
2847 if (rtx_equal_p (OP (1), OP (2)))
2848 OP (2) = OP (1) = move_to_acc (1, insn);
2849 else
2850 OP (1) = move_to_acc (1, insn);
2852 MAYBE_OK (insn);
2854 /* If we omitted the move of OP1 into the accumulator (because
2855 it was already there from a previous insn), then force the
2856 generation of the move instruction now. We know that we
2857 are about to emit a move into HL (or DE) via AX, and hence
2858 our optimization to remove the load of OP1 is no longer valid. */
2859 if (tmp_id == get_max_insn_count ())
2860 force_into_acc (saved_op1, insn);
2862 /* We have to copy op2 to HL (or DE), but that involves AX, which
2863 already has a live value. Emit it before those insns. */
2865 if (prev)
2866 first = next_nonnote_nondebug_insn (prev);
2867 else
2868 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2871 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2873 MUST_BE_OK (insn);
2876 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2877 static void
2878 rl78_alloc_physical_registers_ro1 (rtx_insn *insn)
2880 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2882 MAYBE_OK (insn);
2884 OP (0) = move_to_acc (0, insn);
2886 MUST_BE_OK (insn);
2889 /* Devirtualize a compare insn. */
2890 static void
2891 rl78_alloc_physical_registers_cmp (rtx_insn *insn)
2893 int tmp_id;
2894 rtx saved_op1;
2895 rtx prev = prev_nonnote_nondebug_insn (insn);
2896 rtx first;
2898 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2899 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2901 /* HI compares have to have OP (1) in AX, but QI
2902 compares do not, so it is worth checking here. */
2903 MAYBE_OK (insn);
2905 /* For an HImode compare, OP (1) must always be in AX.
2906 But if OP (1) is a REG (and not AX), then we can avoid
2907 a reload of OP (1) if we reload OP (2) into AX and invert
2908 the comparison. */
2909 if (REG_P (OP (1))
2910 && REGNO (OP (1)) != AX_REG
2911 && GET_MODE (OP (1)) == HImode
2912 && MEM_P (OP (2)))
2914 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
2916 OP (2) = move_to_acc (2, insn);
2918 switch (GET_CODE (cmp))
2920 case EQ:
2921 case NE:
2922 break;
2923 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
2924 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
2925 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
2926 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
2928 case LT:
2929 case GT:
2930 case LE:
2931 case GE:
2932 #if DEBUG_ALLOC
2933 debug_rtx (insn);
2934 #endif
2935 default:
2936 gcc_unreachable ();
2939 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
2940 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
2941 else
2942 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
2944 MUST_BE_OK (insn);
2947 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2948 should be handled by the second alternative of the cbranchhi_real pattern. */
2949 if (rtx_equal_p (OP (1), OP (2)))
2951 OP (1) = OP (2) = BC;
2952 MUST_BE_OK (insn);
2955 tmp_id = get_max_insn_count ();
2956 saved_op1 = OP (1);
2958 OP (1) = move_to_acc (1, insn);
2960 MAYBE_OK (insn);
2962 /* If we omitted the move of OP1 into the accumulator (because
2963 it was already there from a previous insn), then force the
2964 generation of the move instruction now. We know that we
2965 are about to emit a move into HL via AX, and hence our
2966 optimization to remove the load of OP1 is no longer valid. */
2967 if (tmp_id == get_max_insn_count ())
2968 force_into_acc (saved_op1, insn);
2970 /* We have to copy op2 to HL, but that involves the acc, which
2971 already has a live value. Emit it before those insns. */
2972 if (prev)
2973 first = next_nonnote_nondebug_insn (prev);
2974 else
2975 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2977 OP (2) = move_to_hl (2, first);
2979 MUST_BE_OK (insn);
2982 /* Like op2, but AX = A * X. */
2983 static void
2984 rl78_alloc_physical_registers_umul (rtx_insn *insn)
2986 rtx prev = prev_nonnote_nondebug_insn (insn);
2987 rtx first;
2988 int tmp_id;
2989 rtx saved_op1;
2991 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2992 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2993 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2995 MAYBE_OK (insn);
2997 if (recog_data.constraints[1][0] == '%'
2998 && is_virtual_register (OP (1))
2999 && !is_virtual_register (OP (2))
3000 && !CONSTANT_P (OP (2)))
3002 rtx tmp = OP (1);
3003 OP (1) = OP (2);
3004 OP (2) = tmp;
3007 OP (0) = move_from_acc (0, insn);
3009 tmp_id = get_max_insn_count ();
3010 saved_op1 = OP (1);
3012 if (rtx_equal_p (OP (1), OP (2)))
3014 gcc_assert (GET_MODE (OP (2)) == QImode);
3015 /* The MULU instruction does not support duplicate arguments
3016 but we know that if we copy OP (2) to X it will do so via
3017 A and thus OP (1) will already be loaded into A. */
3018 OP (2) = move_to_x (2, insn);
3019 OP (1) = A;
3021 else
3022 OP (1) = move_to_acc (1, insn);
3024 MAYBE_OK (insn);
3026 /* If we omitted the move of OP1 into the accumulator (because
3027 it was already there from a previous insn), then force the
3028 generation of the move instruction now. We know that we
3029 are about to emit a move into HL (or DE) via AX, and hence
3030 our optimization to remove the load of OP1 is no longer valid. */
3031 if (tmp_id == get_max_insn_count ())
3032 force_into_acc (saved_op1, insn);
3034 /* We have to copy op2 to X, but that involves the acc, which
3035 already has a live value. Emit it before those insns. */
3037 if (prev)
3038 first = next_nonnote_nondebug_insn (prev);
3039 else
3040 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
3042 OP (2) = move_to_x (2, first);
3044 MUST_BE_OK (insn);
3047 static void
3048 rl78_alloc_address_registers_macax (rtx_insn *insn)
3050 int which, op;
3051 bool replace_in_op0 = false;
3052 bool replace_in_op1 = false;
3054 MAYBE_OK (insn);
3056 /* Two different MEMs are not allowed. */
3057 which = 0;
3058 for (op = 2; op >= 0; op --)
3060 if (MEM_P (OP (op)))
3062 if (op == 0 && replace_in_op0)
3063 continue;
3064 if (op == 1 && replace_in_op1)
3065 continue;
3067 switch (which)
3069 case 0:
3070 /* If we replace a MEM, make sure that we replace it for all
3071 occurrences of the same MEM in the insn. */
3072 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3073 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3075 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3076 if (op == 2
3077 && MEM_P (OP (op))
3078 && ((GET_CODE (XEXP (OP (op), 0)) == REG
3079 && REGNO (XEXP (OP (op), 0)) == SP_REG)
3080 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3081 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3083 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3084 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3086 if (replace_in_op0)
3087 OP (0) = OP (op);
3088 if (replace_in_op1)
3089 OP (1) = OP (op);
3090 break;
3091 case 1:
3092 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3093 break;
3094 case 2:
3095 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3096 break;
3098 which ++;
3102 MUST_BE_OK (insn);
3105 /* Scan all insns and devirtualize them. */
3106 static void
3107 rl78_alloc_physical_registers (void)
3109 /* During most of the compile, gcc is dealing with virtual
3110 registers. At this point, we need to assign physical registers
3111 to the vitual ones, and copy in/out as needed. */
3113 rtx_insn *insn, *curr;
3114 enum attr_valloc valloc_method;
3116 for (insn = get_insns (); insn; insn = curr)
3118 int i;
3120 curr = next_nonnote_nondebug_insn (insn);
3122 if (INSN_P (insn)
3123 && (GET_CODE (PATTERN (insn)) == SET
3124 || GET_CODE (PATTERN (insn)) == CALL)
3125 && INSN_CODE (insn) == -1)
3127 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3128 continue;
3129 i = recog (PATTERN (insn), insn, 0);
3130 if (i == -1)
3132 debug_rtx (insn);
3133 gcc_unreachable ();
3135 INSN_CODE (insn) = i;
3139 cfun->machine->virt_insns_ok = 0;
3140 cfun->machine->real_insns_ok = 1;
3142 clear_content_memory ();
3144 for (insn = get_insns (); insn; insn = curr)
3146 rtx pattern;
3148 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3150 if (!INSN_P (insn))
3152 if (LABEL_P (insn))
3153 clear_content_memory ();
3155 continue;
3158 if (dump_file)
3159 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3161 pattern = PATTERN (insn);
3162 if (GET_CODE (pattern) == PARALLEL)
3163 pattern = XVECEXP (pattern, 0, 0);
3164 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3165 clear_content_memory ();
3166 if (GET_CODE (pattern) != SET
3167 && GET_CODE (pattern) != CALL)
3168 continue;
3169 if (GET_CODE (pattern) == SET
3170 && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3171 continue;
3173 valloc_method = get_attr_valloc (insn);
3175 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3177 if (valloc_method == VALLOC_MACAX)
3179 record_content (AX, NULL_RTX);
3180 record_content (BC, NULL_RTX);
3181 record_content (DE, NULL_RTX);
3184 if (insn_ok_now (insn))
3185 continue;
3187 INSN_CODE (insn) = -1;
3189 if (RTX_FRAME_RELATED_P (insn))
3190 virt_insn_was_frame = 1;
3191 else
3192 virt_insn_was_frame = 0;
3194 switch (valloc_method)
3196 case VALLOC_OP1:
3197 rl78_alloc_physical_registers_op1 (insn);
3198 break;
3199 case VALLOC_OP2:
3200 rl78_alloc_physical_registers_op2 (insn);
3201 break;
3202 case VALLOC_RO1:
3203 rl78_alloc_physical_registers_ro1 (insn);
3204 break;
3205 case VALLOC_CMP:
3206 rl78_alloc_physical_registers_cmp (insn);
3207 break;
3208 case VALLOC_UMUL:
3209 rl78_alloc_physical_registers_umul (insn);
3210 break;
3211 case VALLOC_MACAX:
3212 /* Macro that clobbers AX. */
3213 rl78_alloc_address_registers_macax (insn);
3214 record_content (AX, NULL_RTX);
3215 record_content (BC, NULL_RTX);
3216 record_content (DE, NULL_RTX);
3217 break;
3220 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3221 clear_content_memory ();
3222 else
3223 process_postponed_content_update ();
3226 #if DEBUG_ALLOC
3227 fprintf (stderr, "\033[0m");
3228 #endif
3231 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3232 This function scans for uses of registers; the last use (i.e. first
3233 encounter when scanning backwards) triggers a REG_DEAD note if the
3234 reg was previously in DEAD[]. */
3235 static void
3236 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3238 const char *fmt;
3239 int i, r;
3240 enum rtx_code code;
3242 if (!s)
3243 return;
3245 code = GET_CODE (s);
3247 switch (code)
3249 /* Compare registers by number. */
3250 case REG:
3251 r = REGNO (s);
3252 if (dump_file)
3254 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3255 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3256 print_rtl_single (dump_file, s);
3258 if (dead [r])
3259 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3260 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3261 dead [r + i] = 0;
3262 return;
3264 /* These codes have no constituent expressions
3265 and are unique. */
3266 case SCRATCH:
3267 case CC0:
3268 case PC:
3269 return;
3271 case CONST_INT:
3272 case CONST_VECTOR:
3273 case CONST_DOUBLE:
3274 case CONST_FIXED:
3275 /* These are kept unique for a given value. */
3276 return;
3278 default:
3279 break;
3282 fmt = GET_RTX_FORMAT (code);
3284 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3286 if (fmt[i] == 'E')
3288 int j;
3289 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3290 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3292 else if (fmt[i] == 'e')
3293 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3297 /* Like the previous function, but scan for SETs instead. */
3298 static void
3299 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3301 int r, i;
3303 if (GET_CODE (d) != REG)
3304 return;
3306 r = REGNO (d);
3307 if (dead [r])
3308 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3309 if (dump_file)
3310 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3311 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3312 dead [r + i] = 1;
3315 /* This is a rather crude register death pass. Death status is reset
3316 at every jump or call insn. */
3317 static void
3318 rl78_calculate_death_notes (void)
3320 char dead[FIRST_PSEUDO_REGISTER];
3321 rtx insn, p, s, d;
3322 int i;
3324 memset (dead, 0, sizeof (dead));
3326 for (insn = get_last_insn ();
3327 insn;
3328 insn = prev_nonnote_nondebug_insn (insn))
3330 if (dump_file)
3332 fprintf (dump_file, "\n--------------------------------------------------");
3333 fprintf (dump_file, "\nDead:");
3334 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3335 if (dead[i])
3336 fprintf (dump_file, " %s", reg_names[i]);
3337 fprintf (dump_file, "\n");
3338 print_rtl_single (dump_file, insn);
3341 switch (GET_CODE (insn))
3343 case INSN:
3344 p = PATTERN (insn);
3345 switch (GET_CODE (p))
3347 case SET:
3348 s = SET_SRC (p);
3349 d = SET_DEST (p);
3350 rl78_note_reg_set (dead, d, insn);
3351 rl78_note_reg_uses (dead, s, insn);
3352 break;
3354 case USE:
3355 rl78_note_reg_uses (dead, p, insn);
3356 break;
3358 default:
3359 break;
3361 break;
3363 case JUMP_INSN:
3364 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3366 memset (dead, 1, sizeof (dead));
3367 /* We expect a USE just prior to this, which will mark
3368 the actual return registers. The USE will have a
3369 death note, but we aren't going to be modifying it
3370 after this pass. */
3371 break;
3373 case CALL_INSN:
3374 memset (dead, 0, sizeof (dead));
3375 break;
3377 default:
3378 break;
3380 if (dump_file)
3381 print_rtl_single (dump_file, insn);
3385 /* Helper function to reset the origins in RP and the age in AGE for
3386 all registers. */
3387 static void
3388 reset_origins (int *rp, int *age)
3390 int i;
3391 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3393 rp[i] = i;
3394 age[i] = 0;
3398 /* The idea behind this optimization is to look for cases where we
3399 move data from A to B to C, and instead move from A to B, and A to
3400 C. If B is a virtual register or memory, this is a big win on its
3401 own. If B turns out to be unneeded after this, it's a bigger win.
3402 For each register, we try to determine where it's value originally
3403 came from, if it's propogated purely through moves (and not
3404 computes). The ORIGINS[] array has the regno for the "origin" of
3405 the value in the [regno] it's indexed by. */
3406 static void
3407 rl78_propogate_register_origins (void)
3409 int origins[FIRST_PSEUDO_REGISTER];
3410 int age[FIRST_PSEUDO_REGISTER];
3411 int i;
3412 rtx_insn *insn, *ninsn = NULL;
3413 rtx pat;
3415 reset_origins (origins, age);
3417 for (insn = get_insns (); insn; insn = ninsn)
3419 ninsn = next_nonnote_nondebug_insn (insn);
3421 if (dump_file)
3423 fprintf (dump_file, "\n");
3424 fprintf (dump_file, "Origins:");
3425 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3426 if (origins[i] != i)
3427 fprintf (dump_file, " r%d=r%d", i, origins[i]);
3428 fprintf (dump_file, "\n");
3429 print_rtl_single (dump_file, insn);
3432 switch (GET_CODE (insn))
3434 case CODE_LABEL:
3435 case BARRIER:
3436 case CALL_INSN:
3437 case JUMP_INSN:
3438 reset_origins (origins, age);
3439 break;
3441 default:
3442 break;
3444 case INSN:
3445 pat = PATTERN (insn);
3447 if (GET_CODE (pat) == PARALLEL)
3449 rtx clobber = XVECEXP (pat, 0, 1);
3450 pat = XVECEXP (pat, 0, 0);
3451 if (GET_CODE (clobber) == CLOBBER
3452 && GET_CODE (XEXP (clobber, 0)) == REG)
3454 int cr = REGNO (XEXP (clobber, 0));
3455 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3456 if (dump_file)
3457 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3458 for (i = 0; i < mb; i++)
3460 origins[cr + i] = cr + i;
3461 age[cr + i] = 0;
3464 else
3465 break;
3468 if (GET_CODE (pat) == SET)
3470 rtx src = SET_SRC (pat);
3471 rtx dest = SET_DEST (pat);
3472 int mb = GET_MODE_SIZE (GET_MODE (dest));
3474 if (GET_CODE (dest) == REG)
3476 int dr = REGNO (dest);
3478 if (GET_CODE (src) == REG)
3480 int sr = REGNO (src);
3481 int same = 1;
3482 int best_age, best_reg;
3484 /* See if the copy is not needed. */
3485 for (i = 0; i < mb; i ++)
3486 if (origins[dr + i] != origins[sr + i])
3487 same = 0;
3488 if (same)
3490 if (dump_file)
3491 fprintf (dump_file, "deleting because dest already has correct value\n");
3492 delete_insn (insn);
3493 break;
3496 if (dr < 8 || sr >= 8)
3498 int ar;
3500 best_age = -1;
3501 best_reg = -1;
3502 /* See if the copy can be made from another
3503 bank 0 register instead, instead of the
3504 virtual src register. */
3505 for (ar = 0; ar < 8; ar += mb)
3507 same = 1;
3508 for (i = 0; i < mb; i ++)
3509 if (origins[ar + i] != origins[sr + i])
3510 same = 0;
3512 /* The chip has some reg-reg move limitations. */
3513 if (mb == 1 && dr > 3)
3514 same = 0;
3516 if (same)
3518 if (best_age == -1 || best_age > age[sr + i])
3520 best_age = age[sr + i];
3521 best_reg = sr;
3526 if (best_reg != -1)
3528 /* FIXME: copy debug info too. */
3529 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3530 sr = best_reg;
3534 for (i = 0; i < mb; i++)
3536 origins[dr + i] = origins[sr + i];
3537 age[dr + i] = age[sr + i] + 1;
3540 else
3542 /* The destination is computed, its origin is itself. */
3543 if (dump_file)
3544 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3545 dr, mb, mb == 1 ? "" : "s");
3546 for (i = 0; i < mb; i ++)
3548 origins[dr + i] = dr + i;
3549 age[dr + i] = 0;
3553 /* Any registers marked with that reg as an origin are reset. */
3554 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3555 if (origins[i] >= dr && origins[i] < dr + mb)
3557 origins[i] = i;
3558 age[i] = 0;
3562 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3563 if (get_attr_valloc (insn) == VALLOC_MACAX)
3565 if (dump_file)
3566 fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
3567 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3568 if (i <= 3 || origins[i] <= 3)
3570 origins[i] = i;
3571 age[i] = 0;
3575 if (GET_CODE (src) == ASHIFT
3576 || GET_CODE (src) == ASHIFTRT
3577 || GET_CODE (src) == LSHIFTRT)
3579 rtx count = XEXP (src, 1);
3580 if (GET_CODE (count) == REG)
3582 /* Special case - our pattern clobbers the count register. */
3583 int r = REGNO (count);
3584 if (dump_file)
3585 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3586 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3587 if (i == r || origins[i] == r)
3589 origins[i] = i;
3590 age[i] = 0;
3595 else if (GET_CODE (pat) == CLOBBER
3596 && GET_CODE (XEXP (pat, 0)) == REG)
3598 if (REG_P (XEXP (pat, 0)))
3600 unsigned int reg = REGNO (XEXP (pat, 0));
3602 origins[reg] = reg;
3603 age[reg] = 0;
3610 /* Remove any SETs where the destination is unneeded. */
3611 static void
3612 rl78_remove_unused_sets (void)
3614 rtx_insn *insn, *ninsn = NULL;
3615 rtx dest;
3617 for (insn = get_insns (); insn; insn = ninsn)
3619 ninsn = next_nonnote_nondebug_insn (insn);
3621 rtx set = single_set (insn);
3622 if (set == NULL)
3623 continue;
3625 dest = SET_DEST (set);
3627 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3628 continue;
3630 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3631 delete_insn (insn);
3635 /* This is the top of the devritualization pass. */
3636 static void
3637 rl78_reorg (void)
3639 /* split2 only happens when optimizing, but we need all movSIs to be
3640 split now. */
3641 if (optimize <= 0)
3642 split_all_insns ();
3644 rl78_alloc_physical_registers ();
3646 if (dump_file)
3648 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3649 print_rtl_with_bb (dump_file, get_insns (), 0);
3652 rl78_propogate_register_origins ();
3653 rl78_calculate_death_notes ();
3655 if (dump_file)
3657 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3658 print_rtl_with_bb (dump_file, get_insns (), 0);
3659 fprintf (dump_file, "\n======================================================================\n");
3662 rl78_remove_unused_sets ();
3664 /* The code after devirtualizing has changed so much that at this point
3665 we might as well just rescan everything. Note that
3666 df_rescan_all_insns is not going to help here because it does not
3667 touch the artificial uses and defs. */
3668 df_finish_pass (true);
3669 if (optimize > 1)
3670 df_live_add_problem ();
3671 df_scan_alloc (NULL);
3672 df_scan_blocks ();
3674 if (optimize)
3675 df_analyze ();
3678 #undef TARGET_RETURN_IN_MEMORY
3679 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3681 static bool
3682 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3684 const HOST_WIDE_INT size = int_size_in_bytes (type);
3685 return (size == -1 || size > 8);
3689 #undef TARGET_RTX_COSTS
3690 #define TARGET_RTX_COSTS rl78_rtx_costs
3692 static bool rl78_rtx_costs (rtx x,
3693 int code,
3694 int outer_code ATTRIBUTE_UNUSED,
3695 int opno ATTRIBUTE_UNUSED,
3696 int * total,
3697 bool speed ATTRIBUTE_UNUSED)
3699 if (code == IF_THEN_ELSE)
3700 return COSTS_N_INSNS (10);
3701 if (GET_MODE (x) == SImode)
3703 switch (code)
3705 case MULT:
3706 if (RL78_MUL_RL78)
3707 *total = COSTS_N_INSNS (14);
3708 else if (RL78_MUL_G13)
3709 *total = COSTS_N_INSNS (29);
3710 else
3711 *total = COSTS_N_INSNS (500);
3712 return true;
3713 case PLUS:
3714 *total = COSTS_N_INSNS (8);
3715 return true;
3716 case ASHIFT:
3717 case ASHIFTRT:
3718 case LSHIFTRT:
3719 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3721 switch (INTVAL (XEXP (x, 1)))
3723 case 0: *total = COSTS_N_INSNS (0); break;
3724 case 1: *total = COSTS_N_INSNS (6); break;
3725 case 2: case 3: case 4: case 5: case 6: case 7:
3726 *total = COSTS_N_INSNS (10); break;
3727 case 8: *total = COSTS_N_INSNS (6); break;
3728 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3729 *total = COSTS_N_INSNS (10); break;
3730 case 16: *total = COSTS_N_INSNS (3); break;
3731 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3732 *total = COSTS_N_INSNS (4); break;
3733 case 24: *total = COSTS_N_INSNS (4); break;
3734 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3735 *total = COSTS_N_INSNS (5); break;
3738 else
3739 *total = COSTS_N_INSNS (10+4*16);
3740 return true;
3743 return false;
3747 #undef TARGET_UNWIND_WORD_MODE
3748 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3750 static machine_mode
3751 rl78_unwind_word_mode (void)
3753 return HImode;
3757 struct gcc_target targetm = TARGET_INITIALIZER;
3759 #include "gt-rl78.h"