* config/rl78/constraints.md: For each W* constraint, rename to C*
[official-gcc.git] / gcc / config / rl78 / rl78.c
blobe7bd3deac7d59d8205021526c82e3530e4b0e514
1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2013 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "output.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "function.h"
35 #include "expr.h"
36 #include "optabs.h"
37 #include "libfuncs.h"
38 #include "recog.h"
39 #include "diagnostic-core.h"
40 #include "toplev.h"
41 #include "reload.h"
42 #include "df.h"
43 #include "ggc.h"
44 #include "tm_p.h"
45 #include "debug.h"
46 #include "target.h"
47 #include "target-def.h"
48 #include "langhooks.h"
49 #include "rl78-protos.h"
50 #include "dumpfile.h"
51 #include "tree-pass.h"
52 #include "context.h"
53 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
54 #include "insn-flags.h" /* for gen_*(). */
56 static inline bool is_interrupt_func (const_tree decl);
57 static inline bool is_brk_interrupt_func (const_tree decl);
58 static void rl78_reorg (void);
61 /* Debugging statements are tagged with DEBUG0 only so that they can
62 be easily enabled individually, by replacing the '0' with '1' as
63 needed. */
64 #define DEBUG0 0
65 #define DEBUG1 1
67 /* REGISTER_NAMES has the names for individual 8-bit registers, but
68 these have the names we need to use when referring to 16-bit
69 register pairs. */
70 static const char * const word_regnames[] =
72 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
74 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
75 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
76 "sp", "ap", "psw", "es", "cs"
79 struct GTY(()) machine_function
81 /* If set, the rest of the fields have been computed. */
82 int computed;
83 /* Which register pairs need to be pushed in the prologue. */
84 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
86 /* These fields describe the frame layout... */
87 /* arg pointer */
88 /* 4 bytes for saved PC */
89 int framesize_regs;
90 /* frame pointer */
91 int framesize_locals;
92 int framesize_outgoing;
93 /* stack pointer */
94 int framesize;
96 /* If set, recog is allowed to match against the "real" patterns. */
97 int real_insns_ok;
98 /* If set, recog is allowed to match against the "virtual" patterns. */
99 int virt_insns_ok;
100 /* Set if the current function needs to clean up any trampolines. */
101 int trampolines_used;
104 /* This is our init_machine_status, as set in
105 rl78_option_override. */
106 static struct machine_function *
107 rl78_init_machine_status (void)
109 struct machine_function *m;
111 m = ggc_alloc_cleared_machine_function ();
112 m->virt_insns_ok = 1;
114 return m;
117 /* Returns whether to run the devirtualization pass. */
118 static bool
119 devirt_gate (void)
121 return true;
124 /* Runs the devirtualization pass. */
125 static unsigned int
126 devirt_pass (void)
128 rl78_reorg ();
129 return 0;
132 /* This pass converts virtual instructions using virtual registers, to
133 real instructions using real registers. Rather than run it as
134 reorg, we reschedule it before vartrack to help with debugging. */
135 namespace {
137 const pass_data pass_data_rl78_devirt =
139 RTL_PASS, /* type */
140 "devirt", /* name */
141 OPTGROUP_NONE, /* optinfo_flags */
142 true, /* has_gate */
143 true, /* has_execute */
144 TV_MACH_DEP, /* tv_id */
145 0, /* properties_required */
146 0, /* properties_provided */
147 0, /* properties_destroyed */
148 0, /* todo_flags_start */
149 0, /* todo_flags_finish */
152 class pass_rl78_devirt : public rtl_opt_pass
154 public:
155 pass_rl78_devirt(gcc::context *ctxt)
156 : rtl_opt_pass(pass_data_rl78_devirt, ctxt)
160 /* opt_pass methods: */
161 bool gate () { return devirt_gate (); }
162 unsigned int execute () { return devirt_pass (); }
165 } // anon namespace
167 rtl_opt_pass *
168 make_pass_rl78_devirt (gcc::context *ctxt)
170 return new pass_rl78_devirt (ctxt);
173 static unsigned int
174 move_elim_pass (void)
176 rtx insn, ninsn, prev = NULL_RTX;
178 for (insn = get_insns (); insn; insn = ninsn)
180 rtx set;
182 ninsn = next_nonnote_nondebug_insn (insn);
184 if ((set = single_set (insn)) == NULL_RTX)
186 prev = NULL_RTX;
187 continue;
190 /* If we have two SET insns in a row (without anything
191 between them) and the source of the second one is the
192 destination of the first one, and vice versa, then we
193 can eliminate the second SET. */
194 if (prev
195 && rtx_equal_p (SET_DEST (prev), SET_SRC (set))
196 && rtx_equal_p (SET_DEST (set), SET_SRC (prev))
199 if (dump_file)
200 fprintf (dump_file, " Delete insn %d because it is redundant\n",
201 INSN_UID (insn));
203 delete_insn (insn);
204 prev = NULL_RTX;
206 else
207 prev = set;
210 if (dump_file)
211 print_rtl_with_bb (dump_file, get_insns (), 0);
213 return 0;
216 namespace {
218 const pass_data pass_data_rl78_move_elim =
220 RTL_PASS, /* type */
221 "move_elim", /* name */
222 OPTGROUP_NONE, /* optinfo_flags */
223 true, /* has_gate */
224 true, /* has_execute */
225 TV_MACH_DEP, /* tv_id */
226 0, /* properties_required */
227 0, /* properties_provided */
228 0, /* properties_destroyed */
229 0, /* todo_flags_start */
230 0, /* todo_flags_finish */
233 class pass_rl78_move_elim : public rtl_opt_pass
235 public:
236 pass_rl78_move_elim(gcc::context *ctxt)
237 : rtl_opt_pass(pass_data_rl78_move_elim, ctxt)
241 /* opt_pass methods: */
242 bool gate () { return devirt_gate (); }
243 unsigned int execute () { return move_elim_pass (); }
246 } // anon namespace
248 rtl_opt_pass *
249 make_pass_rl78_move_elim (gcc::context *ctxt)
251 return new pass_rl78_move_elim (ctxt);
254 #undef TARGET_ASM_FILE_START
255 #define TARGET_ASM_FILE_START rl78_asm_file_start
257 static void
258 rl78_asm_file_start (void)
260 int i;
262 if (TARGET_G10)
264 /* The memory used is 0xffec8 to 0xffedf; real registers are in
265 0xffee0 to 0xffee7. */
266 for (i = 8; i < 32; i++)
267 fprintf (asm_out_file, "r%d\t=\t0x%x\n", i, 0xffec0 + i);
269 else
271 for (i = 0; i < 8; i++)
273 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
274 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
278 opt_pass *rl78_devirt_pass = make_pass_rl78_devirt (g);
279 static struct register_pass_info rl78_devirt_info =
281 rl78_devirt_pass,
282 "pro_and_epilogue",
284 PASS_POS_INSERT_BEFORE
287 opt_pass *rl78_move_elim_pass = make_pass_rl78_move_elim (g);
288 static struct register_pass_info rl78_move_elim_info =
290 rl78_move_elim_pass,
291 "bbro",
293 PASS_POS_INSERT_AFTER
296 register_pass (& rl78_devirt_info);
297 register_pass (& rl78_move_elim_info);
301 #undef TARGET_OPTION_OVERRIDE
302 #define TARGET_OPTION_OVERRIDE rl78_option_override
304 static void
305 rl78_option_override (void)
307 flag_omit_frame_pointer = 1;
308 flag_no_function_cse = 1;
309 flag_split_wide_types = 0;
311 init_machine_status = rl78_init_machine_status;
314 /* Most registers are 8 bits. Some are 16 bits because, for example,
315 gcc doesn't like dealing with $FP as a register pair. This table
316 maps register numbers to size in bytes. */
317 static const int register_sizes[] =
319 1, 1, 1, 1, 1, 1, 1, 1,
320 1, 1, 1, 1, 1, 1, 1, 1,
321 1, 1, 1, 1, 1, 1, 2, 1,
322 1, 1, 1, 1, 1, 1, 1, 1,
323 2, 2, 1, 1, 1
326 /* Predicates used in the MD patterns. This one is true when virtual
327 insns may be matched, which typically means before (or during) the
328 devirt pass. */
329 bool
330 rl78_virt_insns_ok (void)
332 if (cfun)
333 return cfun->machine->virt_insns_ok;
334 return true;
337 /* Predicates used in the MD patterns. This one is true when real
338 insns may be matched, which typically means after (or during) the
339 devirt pass. */
340 bool
341 rl78_real_insns_ok (void)
343 if (cfun)
344 return cfun->machine->real_insns_ok;
345 return false;
348 /* Implements HARD_REGNO_NREGS. */
350 rl78_hard_regno_nregs (int regno, enum machine_mode mode)
352 int rs = register_sizes[regno];
353 if (rs < 1)
354 rs = 1;
355 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
358 /* Implements HARD_REGNO_MODE_OK. */
360 rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
362 int s = GET_MODE_SIZE (mode);
364 if (s < 1)
365 return 0;
366 /* These are not to be used by gcc. */
367 if (regno == 23 || regno == ES_REG || regno == CS_REG)
368 return 0;
369 /* $fp can alway sbe accessed as a 16-bit value. */
370 if (regno == FP_REG && s == 2)
371 return 1;
372 if (regno < SP_REG)
374 /* Since a reg-reg move is really a reg-mem move, we must
375 enforce alignment. */
376 if (s > 1 && (regno % 2))
377 return 0;
378 return 1;
380 if (s == CC_REGNUM)
381 return (mode == BImode);
382 /* All other registers must be accessed in their natural sizes. */
383 if (s == register_sizes [regno])
384 return 1;
385 return 0;
388 /* Simplify_gen_subreg() doesn't handle memory references the way we
389 need it to below, so we use this function for when we must get a
390 valid subreg in a "natural" state. */
391 static rtx
392 rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
394 if (GET_CODE (r) == MEM)
395 return adjust_address (r, mode, byte);
396 else
397 return simplify_gen_subreg (mode, r, omode, byte);
400 /* Used by movsi. Split SImode moves into two HImode moves, using
401 appropriate patterns for the upper and lower halves of symbols. */
402 void
403 rl78_expand_movsi (rtx *operands)
405 rtx op00, op02, op10, op12;
407 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
408 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
409 if (GET_CODE (operands[1]) == CONST
410 || GET_CODE (operands[1]) == SYMBOL_REF)
412 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
413 op10 = gen_rtx_CONST (HImode, op10);
414 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
415 op12 = gen_rtx_CONST (HImode, op12);
417 else
419 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
420 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
423 if (rtx_equal_p (operands[0], operands[1]))
425 else if (rtx_equal_p (op00, op12))
427 emit_move_insn (op02, op12);
428 emit_move_insn (op00, op10);
430 else
432 emit_move_insn (op00, op10);
433 emit_move_insn (op02, op12);
437 void
438 rl78_split_movsi (rtx *operands)
440 rtx op00, op02, op10, op12;
442 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
443 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
444 if (GET_CODE (operands[1]) == CONST
445 || GET_CODE (operands[1]) == SYMBOL_REF)
447 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
448 op10 = gen_rtx_CONST (HImode, op10);
449 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
450 op12 = gen_rtx_CONST (HImode, op12);
452 else
454 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
455 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
458 if (rtx_equal_p (operands[0], operands[1]))
460 else if (rtx_equal_p (op00, op12))
462 operands[2] = op02;
463 operands[4] = op12;
464 operands[3] = op00;
465 operands[5] = op10;
467 else
469 operands[2] = op00;
470 operands[4] = op10;
471 operands[3] = op02;
472 operands[5] = op12;
477 /* Used by various two-operand expanders which cannot accept all
478 operands in the "far" namespace. Force some such operands into
479 registers so that each pattern has at most one far operand. */
481 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
483 int did = 0;
484 rtx temp_reg = NULL;
486 /* FIXME: in the future, be smarter about only doing this if the
487 other operand is also far, assuming the devirtualizer can also
488 handle that. */
489 if (rl78_far_p (operands[0]))
491 temp_reg = operands[0];
492 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
493 did = 1;
495 if (!did)
496 return 0;
498 emit_insn (gen (operands[0], operands[1]));
499 if (temp_reg)
500 emit_move_insn (temp_reg, operands[0]);
501 return 1;
504 /* Likewise, but for three-operand expanders. */
506 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
508 int did = 0;
509 rtx temp_reg = NULL;
511 /* FIXME: Likewise. */
512 if (rl78_far_p (operands[1]))
514 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
515 emit_move_insn (temp_reg, operands[1]);
516 operands[1] = temp_reg;
517 did = 1;
519 if (rl78_far_p (operands[0]))
521 temp_reg = operands[0];
522 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
523 did = 1;
525 if (!did)
526 return 0;
528 emit_insn (gen (operands[0], operands[1], operands[2]));
529 if (temp_reg)
530 emit_move_insn (temp_reg, operands[0]);
531 return 1;
534 #undef TARGET_CAN_ELIMINATE
535 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
537 static bool
538 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
540 return true;
543 /* Returns nonzero if the given register needs to be saved by the
544 current function. */
545 static int
546 need_to_save (int regno)
548 if (is_interrupt_func (cfun->decl))
550 if (regno < 8)
551 return 1; /* don't know what devirt will need */
552 if (regno > 23)
553 return 0; /* don't need to save interrupt registers */
554 if (crtl->is_leaf)
556 return df_regs_ever_live_p (regno);
558 else
559 return 1;
561 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
562 return 1;
563 if (fixed_regs[regno])
564 return 0;
565 if (crtl->calls_eh_return)
566 return 1;
567 if (df_regs_ever_live_p (regno)
568 && !call_used_regs[regno])
569 return 1;
570 return 0;
573 /* We use this to wrap all emitted insns in the prologue. */
574 static rtx
575 F (rtx x)
577 RTX_FRAME_RELATED_P (x) = 1;
578 return x;
581 /* Compute all the frame-related fields in our machine_function
582 structure. */
583 static void
584 rl78_compute_frame_info (void)
586 int i;
588 cfun->machine->computed = 1;
589 cfun->machine->framesize_regs = 0;
590 cfun->machine->framesize_locals = get_frame_size ();
591 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
593 for (i = 0; i < 16; i ++)
594 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
596 cfun->machine->need_to_push [i] = 1;
597 cfun->machine->framesize_regs += 2;
599 else
600 cfun->machine->need_to_push [i] = 0;
602 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
603 cfun->machine->framesize_locals ++;
605 cfun->machine->framesize = (cfun->machine->framesize_regs
606 + cfun->machine->framesize_locals
607 + cfun->machine->framesize_outgoing);
610 /* Returns true if the provided function has the specified attribute. */
611 static inline bool
612 has_func_attr (const_tree decl, const char * func_attr)
614 if (decl == NULL_TREE)
615 decl = current_function_decl;
617 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
620 /* Returns true if the provided function has the "interrupt" attribute. */
621 static inline bool
622 is_interrupt_func (const_tree decl)
624 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
627 /* Returns true if the provided function has the "brk_interrupt" attribute. */
628 static inline bool
629 is_brk_interrupt_func (const_tree decl)
631 return has_func_attr (decl, "brk_interrupt");
634 /* Check "interrupt" attributes. */
635 static tree
636 rl78_handle_func_attribute (tree * node,
637 tree name,
638 tree args,
639 int flags ATTRIBUTE_UNUSED,
640 bool * no_add_attrs)
642 gcc_assert (DECL_P (* node));
643 gcc_assert (args == NULL_TREE);
645 if (TREE_CODE (* node) != FUNCTION_DECL)
647 warning (OPT_Wattributes, "%qE attribute only applies to functions",
648 name);
649 * no_add_attrs = true;
652 /* FIXME: We ought to check that the interrupt and exception
653 handler attributes have been applied to void functions. */
654 return NULL_TREE;
657 #undef TARGET_ATTRIBUTE_TABLE
658 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
660 /* Table of RL78-specific attributes. */
661 const struct attribute_spec rl78_attribute_table[] =
663 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
664 affects_type_identity. */
665 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
666 false },
667 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
668 false },
669 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute,
670 false },
671 { NULL, 0, 0, false, false, false, NULL, false }
676 /* Break down an address RTX into its component base/index/addend
677 portions and return TRUE if the address is of a valid form, else
678 FALSE. */
679 static bool
680 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
682 *base = NULL_RTX;
683 *index = NULL_RTX;
684 *addend = NULL_RTX;
686 if (GET_CODE (x) == REG)
688 *base = x;
689 return true;
692 /* We sometimes get these without the CONST wrapper */
693 if (GET_CODE (x) == PLUS
694 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
695 && GET_CODE (XEXP (x, 1)) == CONST_INT)
697 *addend = x;
698 return true;
701 if (GET_CODE (x) == PLUS)
703 *base = XEXP (x, 0);
704 x = XEXP (x, 1);
706 if (GET_CODE (*base) != REG
707 && GET_CODE (x) == REG)
709 rtx tmp = *base;
710 *base = x;
711 x = tmp;
714 if (GET_CODE (*base) != REG)
715 return false;
717 if (GET_CODE (x) == ZERO_EXTEND
718 && GET_CODE (XEXP (x, 0)) == REG)
720 *index = XEXP (x, 0);
721 return false;
725 switch (GET_CODE (x))
727 case PLUS:
728 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
729 && GET_CODE (XEXP (x, 0)) == CONST_INT)
731 *addend = x;
732 return true;
734 /* fall through */
735 case MEM:
736 case REG:
737 return false;
739 case CONST:
740 case SYMBOL_REF:
741 case CONST_INT:
742 *addend = x;
743 return true;
745 default:
746 return false;
749 return false;
752 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
753 addressing. */
754 bool
755 rl78_hl_b_c_addr_p (rtx op)
757 rtx hl, bc;
759 if (GET_CODE (op) != PLUS)
760 return false;
761 hl = XEXP (op, 0);
762 bc = XEXP (op, 1);
763 if (GET_CODE (hl) == ZERO_EXTEND)
765 rtx tmp = hl;
766 hl = bc;
767 bc = tmp;
769 if (GET_CODE (hl) != REG)
770 return false;
771 if (GET_CODE (bc) != ZERO_EXTEND)
772 return false;
773 bc = XEXP (bc, 0);
774 if (GET_CODE (bc) != REG)
775 return false;
776 if (REGNO (hl) != HL_REG)
777 return false;
778 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
779 return false;
781 return true;
784 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
786 /* Used in various constraints and predicates to match operands in the
787 "far" address space. */
789 rl78_far_p (rtx x)
791 if (! MEM_P (x))
792 return 0;
793 #if DEBUG0
794 fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
795 fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
796 #endif
797 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
800 /* Return the appropriate mode for a named address pointer. */
801 #undef TARGET_ADDR_SPACE_POINTER_MODE
802 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
803 static enum machine_mode
804 rl78_addr_space_pointer_mode (addr_space_t addrspace)
806 switch (addrspace)
808 case ADDR_SPACE_GENERIC:
809 return HImode;
810 case ADDR_SPACE_FAR:
811 return SImode;
812 default:
813 gcc_unreachable ();
817 /* Returns TRUE for valid addresses. */
818 #undef TARGET_VALID_POINTER_MODE
819 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
820 static bool
821 rl78_valid_pointer_mode (enum machine_mode m)
823 return (m == HImode || m == SImode);
826 /* Return the appropriate mode for a named address address. */
827 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
828 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
829 static enum machine_mode
830 rl78_addr_space_address_mode (addr_space_t addrspace)
832 switch (addrspace)
834 case ADDR_SPACE_GENERIC:
835 return HImode;
836 case ADDR_SPACE_FAR:
837 return SImode;
838 default:
839 gcc_unreachable ();
843 #undef TARGET_LEGITIMATE_CONSTANT_P
844 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
846 static bool
847 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
849 return true;
852 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
853 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
855 bool
856 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
857 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
859 rtx base, index, addend;
861 if (GET_CODE (x) == UNSPEC
862 && XINT (x, 1) == UNS_ES_ADDR)
863 x = XVECEXP (x, 0, 1);
865 if (as == ADDR_SPACE_GENERIC
866 && GET_MODE (x) == SImode)
867 return false;
869 if (! characterize_address (x, &base, &index, &addend))
870 return false;
872 /* We can't extract the high/low portions of a PLUS address
873 involving a register during devirtualization, so make sure all
874 such __far addresses do not have addends. This forces GCC to do
875 the sum separately. */
876 if (addend && base && as == ADDR_SPACE_FAR)
877 return false;
879 if (base && index)
881 int ir = REGNO (index);
882 int br = REGNO (base);
884 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
885 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
886 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
887 return false;
890 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
891 return false;
893 if (! cfun->machine->virt_insns_ok && base && GET_CODE (base) == REG
894 && REGNO (base) >= 8 && REGNO (base) <= 31)
895 return false;
897 return true;
900 /* Determine if one named address space is a subset of another. */
901 #undef TARGET_ADDR_SPACE_SUBSET_P
902 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
903 static bool
904 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
906 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
907 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
909 if (subset == superset)
910 return true;
912 else
913 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
916 #undef TARGET_ADDR_SPACE_CONVERT
917 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
918 /* Convert from one address space to another. */
919 static rtx
920 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
922 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
923 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
924 rtx result;
926 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
927 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
929 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
931 /* This is unpredictable, as we're truncating off usable address
932 bits. */
934 result = gen_reg_rtx (HImode);
935 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
936 return result;
938 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
940 /* This always works. */
941 result = gen_reg_rtx (SImode);
942 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
943 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
944 return result;
946 else
947 gcc_unreachable ();
950 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
951 bool
952 rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
953 addr_space_t address_space ATTRIBUTE_UNUSED,
954 int outer_code ATTRIBUTE_UNUSED, int index_code)
956 if (regno <= SP_REG && regno >= 16)
957 return true;
958 if (index_code == REG)
959 return (regno == HL_REG);
960 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
961 return true;
962 return false;
965 /* Implements MODE_CODE_BASE_REG_CLASS. */
966 enum reg_class
967 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
968 addr_space_t address_space ATTRIBUTE_UNUSED,
969 int outer_code ATTRIBUTE_UNUSED,
970 int index_code ATTRIBUTE_UNUSED)
972 return V_REGS;
975 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
976 described in the machine_Function struct definition, above. */
978 rl78_initial_elimination_offset (int from, int to)
980 int rv = 0; /* as if arg to arg */
982 rl78_compute_frame_info ();
984 switch (to)
986 case STACK_POINTER_REGNUM:
987 rv += cfun->machine->framesize_outgoing;
988 rv += cfun->machine->framesize_locals;
989 /* Fall through. */
990 case FRAME_POINTER_REGNUM:
991 rv += cfun->machine->framesize_regs;
992 rv += 4;
993 break;
994 default:
995 gcc_unreachable ();
998 switch (from)
1000 case FRAME_POINTER_REGNUM:
1001 rv -= 4;
1002 rv -= cfun->machine->framesize_regs;
1003 case ARG_POINTER_REGNUM:
1004 break;
1005 default:
1006 gcc_unreachable ();
1009 return rv;
1012 static int
1013 rl78_is_naked_func (void)
1015 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
1018 /* Expand the function prologue (from the prologue pattern). */
1019 void
1020 rl78_expand_prologue (void)
1022 int i, fs;
1023 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1024 int rb = 0;
1026 if (rl78_is_naked_func ())
1027 return;
1029 if (!cfun->machine->computed)
1030 rl78_compute_frame_info ();
1032 if (flag_stack_usage_info)
1033 current_function_static_stack_size = cfun->machine->framesize;
1035 if (is_interrupt_func (cfun->decl) && !TARGET_G10)
1036 emit_insn (gen_sel_rb (GEN_INT (0)));
1038 for (i = 0; i < 16; i++)
1039 if (cfun->machine->need_to_push [i])
1041 if (TARGET_G10)
1043 emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
1044 F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
1046 else {
1047 int need_bank = i/4;
1048 if (need_bank != rb)
1050 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1051 rb = need_bank;
1053 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
1056 if (rb != 0)
1057 emit_insn (gen_sel_rb (GEN_INT (0)));
1059 if (frame_pointer_needed)
1061 F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1062 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
1063 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
1064 gen_rtx_REG (HImode, AX_REG)));
1067 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1068 while (fs > 0)
1070 int fs_byte = (fs > 254) ? 254 : fs;
1071 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
1072 fs -= fs_byte;
1076 /* Expand the function epilogue (from the epilogue pattern). */
1077 void
1078 rl78_expand_epilogue (void)
1080 int i, fs;
1081 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
1082 int rb = 0;
1084 if (rl78_is_naked_func ())
1085 return;
1087 if (frame_pointer_needed)
1089 emit_move_insn (gen_rtx_REG (HImode, AX_REG),
1090 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
1091 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
1092 gen_rtx_REG (HImode, AX_REG));
1094 else
1096 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
1097 while (fs > 0)
1099 int fs_byte = (fs > 254) ? 254 : fs;
1101 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
1102 fs -= fs_byte;
1106 for (i = 15; i >= 0; i--)
1107 if (cfun->machine->need_to_push [i])
1109 if (TARGET_G10)
1111 emit_insn (gen_pop (gen_rtx_REG (HImode, 0)));
1112 emit_move_insn (gen_rtx_REG (HImode, i*2), gen_rtx_REG (HImode, 0));
1114 else
1116 int need_bank = i / 4;
1118 if (need_bank != rb)
1120 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
1121 rb = need_bank;
1123 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
1127 if (rb != 0)
1128 emit_insn (gen_sel_rb (GEN_INT (0)));
1130 if (cfun->machine->trampolines_used)
1131 emit_insn (gen_trampoline_uninit ());
1133 if (is_brk_interrupt_func (cfun->decl))
1134 emit_jump_insn (gen_brk_interrupt_return ());
1135 else if (is_interrupt_func (cfun->decl))
1136 emit_jump_insn (gen_interrupt_return ());
1137 else
1138 emit_jump_insn (gen_rl78_return ());
1141 /* Likewise, for exception handlers. */
1142 void
1143 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
1145 /* FIXME - replace this with an indirect jump with stack adjust. */
1146 emit_jump_insn (gen_rl78_return ());
1149 #undef TARGET_ASM_FUNCTION_PROLOGUE
1150 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1152 /* We don't use this to actually emit the function prologue. We use
1153 this to insert a comment in the asm file describing the
1154 function. */
1155 static void
1156 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
1158 int i;
1160 if (cfun->machine->framesize == 0)
1161 return;
1162 fprintf (file, "\t; start of function\n");
1164 if (cfun->machine->framesize_regs)
1166 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
1167 for (i = 0; i < 16; i ++)
1168 if (cfun->machine->need_to_push[i])
1169 fprintf (file, " %s", word_regnames[i*2]);
1170 fprintf (file, "\n");
1173 if (frame_pointer_needed)
1174 fprintf (file, "\t; $fp points here (r22)\n");
1176 if (cfun->machine->framesize_locals)
1177 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
1178 cfun->machine->framesize_locals == 1 ? "" : "s");
1180 if (cfun->machine->framesize_outgoing)
1181 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
1182 cfun->machine->framesize_outgoing == 1 ? "" : "s");
1185 /* Return an RTL describing where a function return value of type RET_TYPE
1186 is held. */
1188 #undef TARGET_FUNCTION_VALUE
1189 #define TARGET_FUNCTION_VALUE rl78_function_value
1191 static rtx
1192 rl78_function_value (const_tree ret_type,
1193 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1194 bool outgoing ATTRIBUTE_UNUSED)
1196 enum machine_mode mode = TYPE_MODE (ret_type);
1198 return gen_rtx_REG (mode, 8);
1201 #undef TARGET_PROMOTE_FUNCTION_MODE
1202 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1204 static enum machine_mode
1205 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
1206 enum machine_mode mode,
1207 int *punsignedp ATTRIBUTE_UNUSED,
1208 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
1210 return mode;
1213 /* Return an RTL expression describing the register holding a function
1214 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1215 be passed on the stack. CUM describes the previous parameters to the
1216 function and NAMED is false if the parameter is part of a variable
1217 parameter list, or the last named parameter before the start of a
1218 variable parameter list. */
1220 #undef TARGET_FUNCTION_ARG
1221 #define TARGET_FUNCTION_ARG rl78_function_arg
1223 static rtx
1224 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
1225 enum machine_mode mode ATTRIBUTE_UNUSED,
1226 const_tree type ATTRIBUTE_UNUSED,
1227 bool named ATTRIBUTE_UNUSED)
1229 return NULL_RTX;
1232 #undef TARGET_FUNCTION_ARG_ADVANCE
1233 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1235 static void
1236 rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1237 bool named ATTRIBUTE_UNUSED)
1239 int rounded_size;
1240 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1242 rounded_size = ((mode == BLKmode)
1243 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1244 if (rounded_size & 1)
1245 rounded_size ++;
1246 (*cum) += rounded_size;
1249 #undef TARGET_FUNCTION_ARG_BOUNDARY
1250 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1252 static unsigned int
1253 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1254 const_tree type ATTRIBUTE_UNUSED)
1256 return 16;
1259 /* Supported modifier letters:
1261 A - address of a MEM
1262 S - SADDR form of a real register
1263 v - real register corresponding to a virtual register
1264 m - minus - negative of CONST_INT value.
1265 c - inverse of a conditional (NE vs EQ for example)
1266 z - collapsed conditional
1267 s - shift count mod 8
1268 S - shift count mod 16
1269 r - reverse shift count (8-(count mod 8))
1271 h - bottom HI of an SI
1272 H - top HI of an SI
1273 q - bottom QI of an HI
1274 Q - top QI of an HI
1275 e - third QI of an SI (i.e. where the ES register gets values from)
1276 E - fourth QI of an SI (i.e. MSB)
1280 /* Implements the bulk of rl78_print_operand, below. We do it this
1281 way because we need to test for a constant at the top level and
1282 insert the '#', but not test for it anywhere else as we recurse
1283 down into the operand. */
1284 static void
1285 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1287 int need_paren;
1289 switch (GET_CODE (op))
1291 case MEM:
1292 if (letter == 'A')
1293 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1294 else
1296 if (rl78_far_p (op))
1298 fprintf (file, "es:");
1299 op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1));
1301 if (letter == 'H')
1303 op = adjust_address (op, HImode, 2);
1304 letter = 0;
1306 if (letter == 'h')
1308 op = adjust_address (op, HImode, 0);
1309 letter = 0;
1311 if (letter == 'Q')
1313 op = adjust_address (op, QImode, 1);
1314 letter = 0;
1316 if (letter == 'q')
1318 op = adjust_address (op, QImode, 0);
1319 letter = 0;
1321 if (letter == 'e')
1323 op = adjust_address (op, QImode, 2);
1324 letter = 0;
1326 if (letter == 'E')
1328 op = adjust_address (op, QImode, 3);
1329 letter = 0;
1331 if (CONSTANT_P (XEXP (op, 0)))
1333 fprintf (file, "!");
1334 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1336 else if (GET_CODE (XEXP (op, 0)) == PLUS
1337 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1339 fprintf (file, "!");
1340 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1342 else if (GET_CODE (XEXP (op, 0)) == PLUS
1343 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1344 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1346 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1347 fprintf (file, "[");
1348 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1349 fprintf (file, "]");
1351 else
1353 fprintf (file, "[");
1354 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1355 fprintf (file, "]");
1358 break;
1360 case REG:
1361 if (letter == 'Q')
1362 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1363 else if (letter == 'H')
1364 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1365 else if (letter == 'q')
1366 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1367 else if (letter == 'e')
1368 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1369 else if (letter == 'E')
1370 fprintf (file, "%s", reg_names [REGNO (op) + 3]);
1371 else if (letter == 'S')
1372 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1373 else if (GET_MODE (op) == HImode
1374 && ! (REGNO (op) & ~0xfe))
1376 if (letter == 'v')
1377 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1378 else
1379 fprintf (file, "%s", word_regnames [REGNO (op)]);
1381 else
1382 fprintf (file, "%s", reg_names [REGNO (op)]);
1383 break;
1385 case CONST_INT:
1386 if (letter == 'Q')
1387 fprintf (file, "%ld", INTVAL (op) >> 8);
1388 else if (letter == 'H')
1389 fprintf (file, "%ld", INTVAL (op) >> 16);
1390 else if (letter == 'q')
1391 fprintf (file, "%ld", INTVAL (op) & 0xff);
1392 else if (letter == 'h')
1393 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1394 else if (letter == 'e')
1395 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1396 else if (letter == 'E')
1397 fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff);
1398 else if (letter == 'm')
1399 fprintf (file, "%ld", - INTVAL (op));
1400 else if (letter == 's')
1401 fprintf (file, "%ld", INTVAL (op) % 8);
1402 else if (letter == 'S')
1403 fprintf (file, "%ld", INTVAL (op) % 16);
1404 else if (letter == 'r')
1405 fprintf (file, "%ld", 8 - (INTVAL (op) % 8));
1406 else if (letter == 'C')
1407 fprintf (file, "%ld", (INTVAL (op) ^ 0x8000) & 0xffff);
1408 else
1409 fprintf (file, "%ld", INTVAL (op));
1410 break;
1412 case CONST:
1413 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1414 break;
1416 case ZERO_EXTRACT:
1418 int bits = INTVAL (XEXP (op, 1));
1419 int ofs = INTVAL (XEXP (op, 2));
1420 if (bits == 16 && ofs == 0)
1421 fprintf (file, "%%lo16(");
1422 else if (bits == 16 && ofs == 16)
1423 fprintf (file, "%%hi16(");
1424 else if (bits == 8 && ofs == 16)
1425 fprintf (file, "%%hi8(");
1426 else
1427 gcc_unreachable ();
1428 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1429 fprintf (file, ")");
1431 break;
1433 case ZERO_EXTEND:
1434 if (GET_CODE (XEXP (op, 0)) == REG)
1435 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1436 else
1437 print_rtl (file, op);
1438 break;
1440 case PLUS:
1441 need_paren = 0;
1442 if (letter == 'H')
1444 fprintf (file, "%%hi16(");
1445 need_paren = 1;
1446 letter = 0;
1448 if (letter == 'h')
1450 fprintf (file, "%%lo16(");
1451 need_paren = 1;
1452 letter = 0;
1454 if (letter == 'e')
1456 fprintf (file, "%%hi8(");
1457 need_paren = 1;
1458 letter = 0;
1460 if (letter == 'q' || letter == 'Q')
1461 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1463 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1465 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1466 fprintf (file, "+");
1467 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1469 else
1471 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1472 fprintf (file, "+");
1473 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1475 if (need_paren)
1476 fprintf (file, ")");
1477 break;
1479 case SYMBOL_REF:
1480 need_paren = 0;
1481 if (letter == 'H')
1483 fprintf (file, "%%hi16(");
1484 need_paren = 1;
1485 letter = 0;
1487 if (letter == 'h')
1489 fprintf (file, "%%lo16(");
1490 need_paren = 1;
1491 letter = 0;
1493 if (letter == 'e')
1495 fprintf (file, "%%hi8(");
1496 need_paren = 1;
1497 letter = 0;
1499 if (letter == 'q' || letter == 'Q')
1500 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1502 output_addr_const (file, op);
1503 if (need_paren)
1504 fprintf (file, ")");
1505 break;
1507 case CODE_LABEL:
1508 case LABEL_REF:
1509 output_asm_label (op);
1510 break;
1512 case LTU:
1513 if (letter == 'z')
1514 fprintf (file, "#comparison eliminated");
1515 else
1516 fprintf (file, letter == 'c' ? "nc" : "c");
1517 break;
1518 case LEU:
1519 if (letter == 'z')
1520 fprintf (file, "br");
1521 else
1522 fprintf (file, letter == 'c' ? "h" : "nh");
1523 break;
1524 case GEU:
1525 if (letter == 'z')
1526 fprintf (file, "br");
1527 else
1528 fprintf (file, letter == 'c' ? "c" : "nc");
1529 break;
1530 case GTU:
1531 if (letter == 'z')
1532 fprintf (file, "#comparison eliminated");
1533 else
1534 fprintf (file, letter == 'c' ? "nh" : "h");
1535 break;
1536 case EQ:
1537 if (letter == 'z')
1538 fprintf (file, "br");
1539 else
1540 fprintf (file, letter == 'c' ? "nz" : "z");
1541 break;
1542 case NE:
1543 if (letter == 'z')
1544 fprintf (file, "#comparison eliminated");
1545 else
1546 fprintf (file, letter == 'c' ? "z" : "nz");
1547 break;
1549 /* Note: these assume appropriate adjustments were made so that
1550 unsigned comparisons, which is all this chip has, will
1551 work. */
1552 case LT:
1553 if (letter == 'z')
1554 fprintf (file, "#comparison eliminated");
1555 else
1556 fprintf (file, letter == 'c' ? "nc" : "c");
1557 break;
1558 case LE:
1559 if (letter == 'z')
1560 fprintf (file, "br");
1561 else
1562 fprintf (file, letter == 'c' ? "h" : "nh");
1563 break;
1564 case GE:
1565 if (letter == 'z')
1566 fprintf (file, "br");
1567 else
1568 fprintf (file, letter == 'c' ? "c" : "nc");
1569 break;
1570 case GT:
1571 if (letter == 'z')
1572 fprintf (file, "#comparison eliminated");
1573 else
1574 fprintf (file, letter == 'c' ? "nh" : "h");
1575 break;
1577 default:
1578 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1579 break;
1583 #undef TARGET_PRINT_OPERAND
1584 #define TARGET_PRINT_OPERAND rl78_print_operand
1586 static void
1587 rl78_print_operand (FILE * file, rtx op, int letter)
1589 if (CONSTANT_P (op) && letter != 'u' && letter != 's' && letter != 'r' && letter != 'S')
1590 fprintf (file, "#");
1591 rl78_print_operand_1 (file, op, letter);
1594 #undef TARGET_TRAMPOLINE_INIT
1595 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1597 /* Note that the RL78's addressing makes it very difficult to do
1598 trampolines on the stack. So, libgcc has a small pool of
1599 trampolines from which one is allocated to this task. */
1600 static void
1601 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1603 rtx mov_addr, thunk_addr;
1604 rtx function = XEXP (DECL_RTL (fndecl), 0);
1606 mov_addr = adjust_address (m_tramp, HImode, 0);
1607 thunk_addr = gen_reg_rtx (HImode);
1609 function = force_reg (HImode, function);
1610 static_chain = force_reg (HImode, static_chain);
1612 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1613 emit_move_insn (mov_addr, thunk_addr);
1615 cfun->machine->trampolines_used = 1;
1618 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1619 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1621 static rtx
1622 rl78_trampoline_adjust_address (rtx m_tramp)
1624 rtx x = gen_rtx_MEM (HImode, m_tramp);
1625 return x;
1628 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1629 the "normal" compares, specifically, it only has unsigned compares,
1630 so we must synthesize the missing ones. */
1631 void
1632 rl78_expand_compare (rtx *operands)
1634 if (GET_CODE (operands[2]) == MEM)
1635 operands[2] = copy_to_mode_reg (GET_MODE (operands[2]), operands[2]);
1640 /* Define this to 1 if you are debugging the peephole optimizers. */
1641 #define DEBUG_PEEP 0
1643 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1644 The default "word" size is a byte so we can effectively use all the
1645 registers, but we want to do 16-bit moves whenever possible. This
1646 function determines when such a move is an option. */
1647 bool
1648 rl78_peep_movhi_p (rtx *operands)
1650 int i;
1651 rtx m, a;
1653 /* (set (op0) (op1))
1654 (set (op2) (op3)) */
1656 #if DEBUG_PEEP
1657 fprintf (stderr, "\033[33m");
1658 debug_rtx (operands[0]);
1659 debug_rtx (operands[1]);
1660 debug_rtx (operands[2]);
1661 debug_rtx (operands[3]);
1662 fprintf (stderr, "\033[0m");
1663 #endif
1665 /* You can move a constant to memory as QImode, but not HImode. */
1666 if (GET_CODE (operands[0]) == MEM
1667 && GET_CODE (operands[1]) != REG)
1669 #if DEBUG_PEEP
1670 fprintf (stderr, "no peep: move constant to memory\n");
1671 #endif
1672 return false;
1675 if (rtx_equal_p (operands[0], operands[3]))
1677 #if DEBUG_PEEP
1678 fprintf (stderr, "no peep: overlapping\n");
1679 #endif
1680 return false;
1683 for (i = 0; i < 2; i ++)
1685 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1687 #if DEBUG_PEEP
1688 fprintf (stderr, "no peep: different codes\n");
1689 #endif
1690 return false;
1692 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1694 #if DEBUG_PEEP
1695 fprintf (stderr, "no peep: different modes\n");
1696 #endif
1697 return false;
1700 switch (GET_CODE (operands[i]))
1702 case REG:
1703 /* LSB MSB */
1704 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1705 || GET_MODE (operands[i]) != QImode)
1707 #if DEBUG_PEEP
1708 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1709 REGNO (operands[i]), REGNO (operands[i+2]),
1711 #endif
1712 return false;
1714 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1716 #if DEBUG_PEEP
1717 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1718 #endif
1719 return false;
1721 break;
1723 case CONST_INT:
1724 break;
1726 case MEM:
1727 if (GET_MODE (operands[i]) != QImode)
1728 return false;
1729 if (MEM_ALIGN (operands[i]) < 16)
1730 return false;
1731 a = XEXP (operands[i], 0);
1732 if (GET_CODE (a) == CONST)
1733 a = XEXP (a, 0);
1734 if (GET_CODE (a) == PLUS)
1735 a = XEXP (a, 1);
1736 if (GET_CODE (a) == CONST_INT
1737 && INTVAL (a) & 1)
1739 #if DEBUG_PEEP
1740 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1741 debug_rtx (operands[i]);
1742 #endif
1743 return false;
1745 m = adjust_address (operands[i], QImode, 1);
1746 if (! rtx_equal_p (m, operands[i+2]))
1748 #if DEBUG_PEEP
1749 fprintf (stderr, "no peep: wrong mem %d\n", i);
1750 debug_rtx(m);
1751 debug_rtx (operands[i+2]);
1752 #endif
1753 return false;
1755 break;
1757 default:
1758 #if DEBUG_PEEP
1759 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1760 #endif
1761 return false;
1764 #if DEBUG_PEEP
1765 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1766 #endif
1767 return true;
1770 /* Likewise, when a peephole is activated, this function helps compute
1771 the new operands. */
1772 void
1773 rl78_setup_peep_movhi (rtx *operands)
1775 int i;
1777 for (i = 0; i < 2; i ++)
1779 switch (GET_CODE (operands[i]))
1781 case REG:
1782 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1783 break;
1785 case CONST_INT:
1786 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1787 break;
1789 case MEM:
1790 operands[i+4] = adjust_address (operands[i], HImode, 0);
1791 break;
1793 default:
1794 break;
1800 How Devirtualization works in the RL78 GCC port
1802 Background
1804 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1805 bytes of register space, in four banks, memory-mapped. One bank is
1806 the "selected" bank and holds the registers used for primary
1807 operations. Since the registers are memory mapped, often you can
1808 still refer to the unselected banks via memory accesses.
1810 Virtual Registers
1812 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1813 and refers to the other banks via their memory addresses, although
1814 they're treated as regular registers internally. These "virtual"
1815 registers are R8 through R23 (bank3 is reserved for asm-based
1816 interrupt handlers).
1818 There are four machine description files:
1820 rl78.md - common register-independent patterns and definitions
1821 rl78-expand.md - expanders
1822 rl78-virt.md - patterns that match BEFORE devirtualization
1823 rl78-real.md - patterns that match AFTER devirtualization
1825 At least through register allocation and reload, gcc is told that it
1826 can do pretty much anything - but may only use the virtual registers.
1827 GCC cannot properly create the varying addressing modes that the RL78
1828 supports in an efficient way.
1830 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1831 uses the "valloc" attribute in rl78-virt.md for determining the rules
1832 by which it will replace virtual registers with real registers (or
1833 not) and how to make up addressing modes. For example, insns tagged
1834 with "ro1" have a single read-only parameter, which may need to be
1835 moved from memory/constant/vreg to a suitable real register. As part
1836 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1837 patterns and enabling the rl78-real.md patterns. The new patterns'
1838 constraints are used to determine the real registers used. NOTE:
1839 patterns in rl78-virt.md essentially ignore the constrains and rely on
1840 predicates, where the rl78-real.md ones essentially ignore the
1841 predicates and rely on the constraints.
1843 The devirtualization pass is scheduled via the pass manager (despite
1844 being called "rl78_reorg") so it can be scheduled prior to var-track
1845 (the idea is to let gdb know about the new registers). Ideally, it
1846 would be scheduled right after pro/epilogue generation, so the
1847 post-reload optimizers could operate on the real registers, but when I
1848 tried that there were some issues building the target libraries.
1850 During devirtualization, a simple register move optimizer is run. It
1851 would be better to run a full CSE/propogation pass on it through, or
1852 re-run regmove, but that has not yet been attempted.
1855 #define DEBUG_ALLOC 0
1857 #define OP(x) (*recog_data.operand_loc[x])
1859 /* This array is used to hold knowledge about the contents of the
1860 real registers (A ... H), the memory-based registers (r8 ... r31)
1861 and the first NUM_STACK_LOCS words on the stack. We use this to
1862 avoid generating redundant move instructions.
1864 A value in the range 0 .. 31 indicates register A .. r31.
1865 A value in the range 32 .. 63 indicates stack slot (value - 32).
1866 A value of NOT_KNOWN indicates that the contents of that location
1867 are not known. */
1869 #define NUM_STACK_LOCS 32
1870 #define NOT_KNOWN 127
1872 static unsigned char content_memory [32 + NUM_STACK_LOCS];
1874 static unsigned char saved_update_index = NOT_KNOWN;
1875 static unsigned char saved_update_value;
1876 static enum machine_mode saved_update_mode;
1879 static inline void
1880 clear_content_memory (void)
1882 memset (content_memory, NOT_KNOWN, sizeof content_memory);
1883 if (dump_file)
1884 fprintf (dump_file, " clear content memory\n");
1885 saved_update_index = NOT_KNOWN;
1888 /* Convert LOC into an index into the content_memory array.
1889 If LOC cannot be converted, return NOT_KNOWN. */
1891 static unsigned char
1892 get_content_index (rtx loc)
1894 enum machine_mode mode;
1896 if (loc == NULL_RTX)
1897 return NOT_KNOWN;
1899 if (REG_P (loc))
1901 if (REGNO (loc) < 32)
1902 return REGNO (loc);
1903 return NOT_KNOWN;
1906 mode = GET_MODE (loc);
1908 if (! rl78_stack_based_mem (loc, mode))
1909 return NOT_KNOWN;
1911 loc = XEXP (loc, 0);
1913 if (REG_P (loc))
1914 /* loc = MEM (SP) */
1915 return 32;
1917 /* loc = MEM (PLUS (SP, INT)). */
1918 loc = XEXP (loc, 1);
1920 if (INTVAL (loc) < NUM_STACK_LOCS)
1921 return 32 + INTVAL (loc);
1923 return NOT_KNOWN;
1926 /* Return a string describing content INDEX in mode MODE.
1927 WARNING: Can return a pointer to a static buffer. */
1929 static const char *
1930 get_content_name (unsigned char index, enum machine_mode mode)
1932 static char buffer [128];
1934 if (index == NOT_KNOWN)
1935 return "Unknown";
1937 if (index > 31)
1938 sprintf (buffer, "stack slot %d", index - 32);
1939 else if (mode == HImode)
1940 sprintf (buffer, "%s%s",
1941 reg_names [index + 1], reg_names [index]);
1942 else
1943 return reg_names [index];
1945 return buffer;
1948 #if DEBUG_ALLOC
1950 static void
1951 display_content_memory (FILE * file)
1953 unsigned int i;
1955 fprintf (file, " Known memory contents:\n");
1957 for (i = 0; i < sizeof content_memory; i++)
1958 if (content_memory[i] != NOT_KNOWN)
1960 fprintf (file, " %s contains a copy of ", get_content_name (i, QImode));
1961 fprintf (file, "%s\n", get_content_name (content_memory [i], QImode));
1964 #endif
1966 static void
1967 update_content (unsigned char index, unsigned char val, enum machine_mode mode)
1969 unsigned int i;
1971 gcc_assert (index < sizeof content_memory);
1973 content_memory [index] = val;
1974 if (val != NOT_KNOWN)
1975 content_memory [val] = index;
1977 /* Make the entry in dump_file *before* VAL is increased below. */
1978 if (dump_file)
1980 fprintf (dump_file, " %s now contains ", get_content_name (index, mode));
1981 if (val == NOT_KNOWN)
1982 fprintf (dump_file, "Unknown\n");
1983 else
1984 fprintf (dump_file, "%s and vice versa\n", get_content_name (val, mode));
1987 if (mode == HImode)
1989 val = val == NOT_KNOWN ? val : val + 1;
1991 content_memory [index + 1] = val;
1992 if (val != NOT_KNOWN)
1994 content_memory [val] = index + 1;
1995 -- val;
1999 /* Any other places that had INDEX recorded as their contents are now invalid. */
2000 for (i = 0; i < sizeof content_memory; i++)
2002 if (i == index
2003 || (val != NOT_KNOWN && i == val))
2005 if (mode == HImode)
2006 ++ i;
2007 continue;
2010 if (content_memory[i] == index
2011 || (val != NOT_KNOWN && content_memory[i] == val))
2013 content_memory[i] = NOT_KNOWN;
2015 if (dump_file)
2016 fprintf (dump_file, " %s cleared\n", get_content_name (i, mode));
2018 if (mode == HImode)
2019 content_memory[++ i] = NOT_KNOWN;
2024 /* Record that LOC contains VALUE.
2025 For HImode locations record that LOC+1 contains VALUE+1.
2026 If LOC is not a register or stack slot, do nothing.
2027 If VALUE is not a register or stack slot, clear the recorded content. */
2029 static void
2030 record_content (rtx loc, rtx value)
2032 enum machine_mode mode;
2033 unsigned char index;
2034 unsigned char val;
2036 if ((index = get_content_index (loc)) == NOT_KNOWN)
2037 return;
2039 val = get_content_index (value);
2041 mode = GET_MODE (loc);
2043 if (val == index)
2045 if (! optimize)
2046 return;
2048 /* This should not happen when optimizing. */
2049 #if 1
2050 fprintf (stderr, "ASSIGNMENT of location to itself detected! [%s]\n",
2051 get_content_name (val, mode));
2052 return;
2053 #else
2054 gcc_unreachable ();
2055 #endif
2058 update_content (index, val, mode);
2061 /* Returns TRUE if LOC already contains a copy of VALUE. */
2063 static bool
2064 already_contains (rtx loc, rtx value)
2066 unsigned char index;
2067 unsigned char val;
2069 if ((index = get_content_index (loc)) == NOT_KNOWN)
2070 return false;
2072 if ((val = get_content_index (value)) == NOT_KNOWN)
2073 return false;
2075 if (content_memory [index] != val)
2076 return false;
2078 if (GET_MODE (loc) == HImode)
2079 return content_memory [index + 1] == val + 1;
2081 return true;
2084 bool
2085 rl78_es_addr (rtx addr)
2087 if (GET_CODE (addr) == MEM)
2088 addr = XEXP (addr, 0);
2089 if (GET_CODE (addr) != UNSPEC)
2090 return false;
2091 if (XINT (addr, 1) != UNS_ES_ADDR)
2092 return false;
2093 return true;
2097 rl78_es_base (rtx addr)
2099 if (GET_CODE (addr) == MEM)
2100 addr = XEXP (addr, 0);
2101 addr = XVECEXP (addr, 0, 1);
2102 if (GET_CODE (addr) == CONST
2103 && GET_CODE (XEXP (addr, 0)) == ZERO_EXTRACT)
2104 addr = XEXP (XEXP (addr, 0), 0);
2105 /* Mode doesn't matter here. */
2106 return gen_rtx_MEM (HImode, addr);
2109 /* Rescans an insn to see if it's recognized again. This is done
2110 carefully to ensure that all the constraint information is accurate
2111 for the newly matched insn. */
2112 static bool
2113 insn_ok_now (rtx insn)
2115 rtx pattern = PATTERN (insn);
2116 int i;
2118 INSN_CODE (insn) = -1;
2120 if (recog (pattern, insn, 0) > -1)
2122 extract_insn (insn);
2123 if (constrain_operands (1))
2125 #if DEBUG_ALLOC
2126 fprintf (stderr, "\033[32m");
2127 debug_rtx (insn);
2128 fprintf (stderr, "\033[0m");
2129 #endif
2130 if (SET_P (pattern))
2131 record_content (SET_DEST (pattern), SET_SRC (pattern));
2133 /* We need to detect far addresses that haven't been
2134 converted to es/lo16 format. */
2135 for (i=0; i<recog_data.n_operands; i++)
2136 if (GET_CODE (OP(i)) == MEM
2137 && GET_MODE (XEXP (OP(i), 0)) == SImode
2138 && GET_CODE (XEXP (OP(i), 0)) != UNSPEC)
2139 return false;
2141 return true;
2144 else
2146 /* We need to re-recog the insn with virtual registers to get
2147 the operands */
2148 cfun->machine->virt_insns_ok = 1;
2149 if (recog (pattern, insn, 0) > -1)
2151 extract_insn (insn);
2152 if (constrain_operands (0))
2154 cfun->machine->virt_insns_ok = 0;
2155 return false;
2159 #if DEBUG_ALLOC
2160 fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2161 debug_rtx (insn);
2162 #endif
2163 gcc_unreachable ();
2166 #if DEBUG_ALLOC
2167 fprintf (stderr, "\033[31m");
2168 debug_rtx (insn);
2169 fprintf (stderr, "\033[0m");
2170 #endif
2171 return false;
2174 #if DEBUG_ALLOC
2175 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2176 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2177 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2178 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2179 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2180 #else
2181 #define FAILED gcc_unreachable ()
2182 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2183 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2184 #endif
2186 /* Registers into which we move the contents of virtual registers. */
2187 #define X gen_rtx_REG (QImode, 0)
2188 #define A gen_rtx_REG (QImode, 1)
2189 #define C gen_rtx_REG (QImode, 2)
2190 #define B gen_rtx_REG (QImode, 3)
2191 #define E gen_rtx_REG (QImode, 4)
2192 #define D gen_rtx_REG (QImode, 5)
2193 #define L gen_rtx_REG (QImode, 6)
2194 #define H gen_rtx_REG (QImode, 7)
2196 #define AX gen_rtx_REG (HImode, 0)
2197 #define BC gen_rtx_REG (HImode, 2)
2198 #define DE gen_rtx_REG (HImode, 4)
2199 #define HL gen_rtx_REG (HImode, 6)
2201 /* Returns TRUE if R is a virtual register. */
2202 static bool
2203 is_virtual_register (rtx r)
2205 return (GET_CODE (r) == REG
2206 && REGNO (r) >= 8
2207 && REGNO (r) < 24);
2210 /* In all these alloc routines, we expect the following: the insn
2211 pattern is unshared, the insn was previously recognized and failed
2212 due to predicates or constraints, and the operand data is in
2213 recog_data. */
2215 static int virt_insn_was_frame;
2217 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2218 needed. */
2219 static rtx
2220 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
2222 #if DEBUG_ALLOC
2223 fprintf (stderr, "\033[36m%d: ", line);
2224 debug_rtx(r);
2225 fprintf (stderr, "\033[0m");
2226 #endif
2227 /*SCHED_GROUP_P (r) = 1;*/
2228 if (virt_insn_was_frame)
2229 RTX_FRAME_RELATED_P (r) = 1;
2230 return r;
2233 #define EM(x) EM2 (__LINE__, x)
2235 /* Return a suitable RTX for the low half of a __far address. */
2236 static rtx
2237 rl78_lo16 (rtx addr)
2239 rtx r;
2241 if (GET_CODE (addr) == SYMBOL_REF
2242 || GET_CODE (addr) == CONST)
2244 r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
2245 r = gen_rtx_CONST (HImode, r);
2247 else
2248 r = rl78_subreg (HImode, addr, SImode, 0);
2250 r = gen_es_addr (r);
2252 return r;
2255 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2256 static rtx
2257 rl78_hi8 (rtx addr)
2259 if (GET_CODE (addr) == SYMBOL_REF
2260 || GET_CODE (addr) == CONST)
2262 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
2263 r = gen_rtx_CONST (QImode, r);
2264 return r;
2266 return rl78_subreg (QImode, addr, SImode, 2);
2269 static void
2270 add_postponed_content_update (rtx to, rtx value)
2272 unsigned char index;
2274 if ((index = get_content_index (to)) == NOT_KNOWN)
2275 return;
2277 gcc_assert (saved_update_index == NOT_KNOWN);
2278 saved_update_index = index;
2279 saved_update_value = get_content_index (value);
2280 saved_update_mode = GET_MODE (to);
2283 static void
2284 process_postponed_content_update (void)
2286 if (saved_update_index != NOT_KNOWN)
2288 update_content (saved_update_index, saved_update_value, saved_update_mode);
2289 saved_update_index = NOT_KNOWN;
2293 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2294 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2295 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2296 BEFORE is true, FROM otherwise. */
2297 static rtx
2298 gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
2300 enum machine_mode mode = GET_MODE (to);
2302 if (optimize && before && already_contains (to, from))
2304 #if DEBUG_ALLOC
2305 display_content_memory (stderr);
2306 #endif
2307 if (dump_file)
2309 fprintf (dump_file, " Omit move of %s into ",
2310 get_content_name (get_content_index (from), mode));
2311 fprintf (dump_file, "%s as it already contains this value\n",
2312 get_content_name (get_content_index (to), mode));
2315 else
2317 rtx move = mode == QImode ? gen_movqi (to, from) : gen_movhi (to, from);
2319 EM (move);
2321 if (where == NULL_RTX)
2322 emit_insn (move);
2323 else if (before)
2324 emit_insn_before (move, where);
2325 else
2327 rtx note = find_reg_note (where, REG_EH_REGION, NULL_RTX);
2329 /* If necessary move REG_EH_REGION notes forward.
2330 cf. compiling gcc.dg/pr44545.c. */
2331 if (note != NULL_RTX)
2333 add_reg_note (move, REG_EH_REGION, XEXP (note, 0));
2334 remove_note (where, note);
2337 emit_insn_after (move, where);
2340 if (before)
2341 record_content (to, from);
2342 else
2343 add_postponed_content_update (to, from);
2345 return before ? to : from;
2348 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2349 copy it into NEWBASE and return the updated MEM. Otherwise just
2350 return M. Any needed insns are emitted before BEFORE. */
2351 static rtx
2352 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
2354 rtx base, index, addendr;
2355 int addend = 0;
2356 int need_es = 0;
2358 if (! MEM_P (m))
2359 return m;
2361 if (GET_MODE (XEXP (m, 0)) == SImode)
2363 rtx seg = rl78_hi8 (XEXP (m, 0));
2364 #if DEBUG_ALLOC
2365 fprintf (stderr, "setting ES:\n");
2366 debug_rtx(seg);
2367 #endif
2368 emit_insn_before (EM (gen_movqi (A, seg)), before);
2369 emit_insn_before (EM (gen_movqi_es (A)), before);
2370 record_content (A, NULL_RTX);
2372 m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
2373 need_es = 1;
2376 characterize_address (XEXP (m, 0), & base, & index, & addendr);
2377 gcc_assert (index == NULL_RTX);
2379 #if DEBUG_ALLOC
2380 fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m");
2381 debug_rtx (base);
2382 #endif
2383 if (base == NULL_RTX)
2384 return m;
2386 if (addendr && GET_CODE (addendr) == CONST_INT)
2387 addend = INTVAL (addendr);
2389 gcc_assert (REG_P (base));
2390 gcc_assert (REG_P (newbase));
2392 if (REGNO (base) == SP_REG)
2394 if (addend >= 0 && addend <= 255)
2395 return m;
2398 /* BASE should be a virtual register. We copy it to NEWBASE. If
2399 the addend is out of range for DE/HL, we use AX to compute the full
2400 address. */
2402 if (addend < 0
2403 || (addend > 255 && REGNO (newbase) != 2)
2404 || (addendr && GET_CODE (addendr) != CONST_INT))
2406 /* mov ax, vreg
2407 add ax, #imm
2408 mov hl, ax */
2409 EM (emit_insn_before (gen_movhi (AX, base), before));
2410 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
2411 EM (emit_insn_before (gen_movhi (newbase, AX), before));
2412 record_content (AX, NULL_RTX);
2413 record_content (newbase, NULL_RTX);
2415 base = newbase;
2416 addend = 0;
2418 else
2420 base = gen_and_emit_move (newbase, base, before, true);
2423 if (addend)
2425 record_content (base, NULL_RTX);
2426 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
2429 #if DEBUG_ALLOC
2430 fprintf (stderr, "\033[33m");
2431 debug_rtx (m);
2432 #endif
2433 if (need_es)
2434 m = change_address (m, GET_MODE (m), gen_es_addr (base));
2435 else
2436 m = change_address (m, GET_MODE (m), base);
2437 #if DEBUG_ALLOC
2438 debug_rtx (m);
2439 fprintf (stderr, "\033[0m");
2440 #endif
2441 return m;
2444 /* Copy SRC to accumulator (A or AX), placing any generated insns
2445 before BEFORE. Returns accumulator RTX. */
2447 static rtx
2448 move_to_acc (int opno, rtx before)
2450 rtx src = OP (opno);
2451 enum machine_mode mode = GET_MODE (src);
2453 if (REG_P (src) && REGNO (src) < 2)
2454 return src;
2456 if (mode == VOIDmode)
2457 mode = recog_data.operand_mode[opno];
2459 return gen_and_emit_move (mode == QImode ? A : AX, src, before, true);
2462 static void
2463 force_into_acc (rtx src, rtx before)
2465 enum machine_mode mode = GET_MODE (src);
2466 rtx move;
2468 if (REG_P (src) && REGNO (src) < 2)
2469 return;
2471 move = mode == QImode ? gen_movqi (A, src) : gen_movhi (AX, src);
2473 EM (move);
2475 emit_insn_before (move, before);
2476 record_content (AX, NULL_RTX);
2479 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2480 after AFTER. Returns accumulator RTX. */
2482 static rtx
2483 move_from_acc (unsigned int opno, rtx after)
2485 rtx dest = OP (opno);
2486 enum machine_mode mode = GET_MODE (dest);
2488 if (REG_P (dest) && REGNO (dest) < 2)
2489 return dest;
2491 return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
2494 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2495 before BEFORE. Returns reg RTX. */
2497 static rtx
2498 move_acc_to_reg (rtx acc, int regno, rtx before)
2500 enum machine_mode mode = GET_MODE (acc);
2501 rtx reg;
2503 reg = gen_rtx_REG (mode, regno);
2505 return gen_and_emit_move (reg, acc, before, true);
2508 /* Copy SRC to X, placing any generated insns before BEFORE.
2509 Returns X RTX. */
2511 static rtx
2512 move_to_x (int opno, rtx before)
2514 rtx src = OP (opno);
2515 enum machine_mode mode = GET_MODE (src);
2516 rtx reg;
2518 if (mode == VOIDmode)
2519 mode = recog_data.operand_mode[opno];
2520 reg = (mode == QImode) ? X : AX;
2522 if (mode == QImode || ! is_virtual_register (OP (opno)))
2524 OP (opno) = move_to_acc (opno, before);
2525 OP (opno) = move_acc_to_reg (OP(opno), X_REG, before);
2526 return reg;
2529 return gen_and_emit_move (reg, src, before, true);
2532 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
2533 Returns H/HL RTX. */
2535 static rtx
2536 move_to_hl (int opno, rtx before)
2538 rtx src = OP (opno);
2539 enum machine_mode mode = GET_MODE (src);
2540 rtx reg;
2542 if (mode == VOIDmode)
2543 mode = recog_data.operand_mode[opno];
2544 reg = (mode == QImode) ? L : HL;
2546 if (mode == QImode || ! is_virtual_register (OP (opno)))
2548 OP (opno) = move_to_acc (opno, before);
2549 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
2550 return reg;
2553 return gen_and_emit_move (reg, src, before, true);
2556 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
2557 Returns E/DE RTX. */
2559 static rtx
2560 move_to_de (int opno, rtx before)
2562 rtx src = OP (opno);
2563 enum machine_mode mode = GET_MODE (src);
2564 rtx reg;
2566 if (mode == VOIDmode)
2567 mode = recog_data.operand_mode[opno];
2569 reg = (mode == QImode) ? E : DE;
2571 if (mode == QImode || ! is_virtual_register (OP (opno)))
2573 OP (opno) = move_to_acc (opno, before);
2574 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
2576 else
2578 gen_and_emit_move (reg, src, before, true);
2581 return reg;
2584 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2585 static void
2586 rl78_alloc_physical_registers_op1 (rtx insn)
2588 /* op[0] = func op[1] */
2590 /* We first try using A as the destination, then copying it
2591 back. */
2592 if (rtx_equal_p (OP (0), OP (1)))
2594 OP (0) =
2595 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2597 else
2599 /* If necessary, load the operands into BC and HL.
2600 Check to see if we already have OP (0) in HL
2601 and if so, swap the order. */
2602 if (MEM_P (OP (0))
2603 && already_contains (HL, XEXP (OP (0), 0)))
2605 OP (0) = transcode_memory_rtx (OP (0), HL, insn);
2606 OP (1) = transcode_memory_rtx (OP (1), BC, insn);
2608 else
2610 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2611 OP (1) = transcode_memory_rtx (OP (1), HL, insn);
2615 MAYBE_OK (insn);
2617 OP (0) = move_from_acc (0, insn);
2619 MAYBE_OK (insn);
2621 /* Try copying the src to acc first, then. This is for, for
2622 example, ZERO_EXTEND or NOT. */
2623 OP (1) = move_to_acc (1, insn);
2625 MUST_BE_OK (insn);
2628 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2629 Assumes that the current insn has already been recognised and hence the
2630 constraint data has been filled in. */
2631 static bool
2632 has_constraint (unsigned int opnum, enum constraint_num constraint)
2634 const char * p = recog_data.constraints[opnum];
2636 /* No constraints means anything is accepted. */
2637 if (p == NULL || *p == 0 || *p == ',')
2638 return true;
2642 char c;
2643 unsigned int len;
2645 c = *p;
2646 len = CONSTRAINT_LEN (c, p);
2647 gcc_assert (len > 0);
2649 switch (c)
2651 case 0:
2652 case ',':
2653 return false;
2654 default:
2655 if (lookup_constraint (p) == constraint)
2656 return true;
2658 p += len;
2660 while (1);
2663 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2664 static void
2665 rl78_alloc_physical_registers_op2 (rtx insn)
2667 rtx prev;
2668 rtx first;
2669 bool hl_used;
2670 int tmp_id;
2671 rtx saved_op1;
2673 if (rtx_equal_p (OP (0), OP (1)))
2675 OP (0) =
2676 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2677 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2679 else if (rtx_equal_p (OP (0), OP (2)))
2681 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2682 OP (0) =
2683 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2685 else
2687 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2688 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2689 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2692 MAYBE_OK (insn);
2694 prev = prev_nonnote_nondebug_insn (insn);
2695 if (recog_data.constraints[1][0] == '%'
2696 && is_virtual_register (OP (1))
2697 && ! is_virtual_register (OP (2))
2698 && ! CONSTANT_P (OP (2)))
2700 rtx tmp = OP (1);
2701 OP (1) = OP (2);
2702 OP (2) = tmp;
2705 /* Make a note of whether (H)L is being used. It matters
2706 because if OP (2) alsoneeds reloading, then we must take
2707 care not to corrupt HL. */
2708 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2710 /* If HL is not currently being used and dest == op1 then there are
2711 some possible optimizations available by reloading one of the
2712 operands into HL, before trying to use the accumulator. */
2713 if (optimize
2714 && ! hl_used
2715 && rtx_equal_p (OP (0), OP (1)))
2717 /* If op0 is a Ws1 type memory address then switching the base
2718 address register to HL might allow us to perform an in-memory
2719 operation. (eg for the INCW instruction).
2721 FIXME: Adding the move into HL is costly if this optimization is not
2722 going to work, so for now, make sure that we know that the new insn will
2723 match the requirements of the addhi3_real pattern. Really we ought to
2724 generate a candidate sequence, test that, and then install it if the
2725 results are good. */
2726 if (satisfies_constraint_Ws1 (OP (0))
2727 && has_constraint (0, CONSTRAINT_Wh1)
2728 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2730 rtx base, index, addend, newbase;
2732 characterize_address (XEXP (OP (0), 0), & base, & index, & addend);
2733 gcc_assert (index == NULL_RTX);
2734 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2736 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2737 if (addend != NULL_RTX)
2739 newbase = gen_and_emit_move (HL, base, insn, true);
2740 record_content (newbase, NULL_RTX);
2741 newbase = gen_rtx_PLUS (HImode, newbase, addend);
2743 OP (0) = OP (1) = change_address (OP (0), VOIDmode, newbase);
2745 /* We do not want to fail here as this means that
2746 we have inserted useless insns into the stream. */
2747 MUST_BE_OK (insn);
2750 else if (REG_P (OP (0))
2751 && satisfies_constraint_Ws1 (OP (2))
2752 && has_constraint (2, CONSTRAINT_Wh1))
2754 rtx base, index, addend, newbase;
2756 characterize_address (XEXP (OP (2), 0), & base, & index, & addend);
2757 gcc_assert (index == NULL_RTX);
2758 gcc_assert (REG_P (base) && REGNO (base) == SP_REG);
2760 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2761 if (addend != NULL_RTX)
2763 gen_and_emit_move (HL, base, insn, true);
2765 if (REGNO (OP (0)) != X_REG)
2767 OP (1) = move_to_acc (1, insn);
2768 OP (0) = move_from_acc (0, insn);
2771 record_content (HL, NULL_RTX);
2772 newbase = gen_rtx_PLUS (HImode, HL, addend);
2774 OP (2) = change_address (OP (2), VOIDmode, newbase);
2776 /* We do not want to fail here as this means that
2777 we have inserted useless insns into the stream. */
2778 MUST_BE_OK (insn);
2784 OP (0) = move_from_acc (0, insn);
2786 tmp_id = get_max_insn_count ();
2787 saved_op1 = OP (1);
2789 if (rtx_equal_p (OP (1), OP (2)))
2790 OP (2) = OP (1) = move_to_acc (1, insn);
2791 else
2792 OP (1) = move_to_acc (1, insn);
2794 MAYBE_OK (insn);
2796 /* If we omitted the move of OP1 into the accumulator (because
2797 it was already there from a previous insn), then force the
2798 generation of the move instruction now. We know that we
2799 are about to emit a move into HL (or DE) via AX, and hence
2800 our optimization to remove the load of OP1 is no longer valid. */
2801 if (tmp_id == get_max_insn_count ())
2802 force_into_acc (saved_op1, insn);
2804 /* We have to copy op2 to HL (or DE), but that involves AX, which
2805 already has a live value. Emit it before those insns. */
2807 if (prev)
2808 first = next_nonnote_nondebug_insn (prev);
2809 else
2810 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2813 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2815 MUST_BE_OK (insn);
2818 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2820 static void
2821 rl78_alloc_physical_registers_ro1 (rtx insn)
2823 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2825 MAYBE_OK (insn);
2827 OP (0) = move_to_acc (0, insn);
2829 MUST_BE_OK (insn);
2832 /* Devirtualize a compare insn. */
2834 static void
2835 rl78_alloc_physical_registers_cmp (rtx insn)
2837 int tmp_id;
2838 rtx saved_op1;
2839 rtx prev = prev_nonnote_nondebug_insn (insn);
2840 rtx first;
2842 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2843 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2845 /* HI compares have to have OP(1) in AX, but QI
2846 compares do not, so it is worth checking here. */
2847 MAYBE_OK (insn);
2849 /* For an HImode compare, OP(1) must always be in AX.
2850 But if OP(1) is a REG (and not AX), then we can avoid
2851 a reload of OP(1) if we reload OP(2) into AX and invert
2852 the comparison. */
2853 if (REG_P (OP (1))
2854 && REGNO (OP (1)) != AX_REG
2855 && GET_MODE (OP (1)) == HImode
2856 && MEM_P (OP (2)))
2858 rtx cmp = XEXP (SET_SRC (PATTERN (insn)), 0);
2860 OP (2) = move_to_acc (2, insn);
2862 switch (GET_CODE (cmp))
2864 case EQ:
2865 case NE:
2866 break;
2867 case LTU: cmp = gen_rtx_GTU (HImode, OP (2), OP (1)); break;
2868 case GTU: cmp = gen_rtx_LTU (HImode, OP (2), OP (1)); break;
2869 case LEU: cmp = gen_rtx_GEU (HImode, OP (2), OP (1)); break;
2870 case GEU: cmp = gen_rtx_LEU (HImode, OP (2), OP (1)); break;
2872 case LT:
2873 case GT:
2874 case LE:
2875 case GE:
2876 #if DEBUG_ALLOC
2877 debug_rtx (insn);
2878 #endif
2879 default:
2880 gcc_unreachable ();
2883 if (GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
2884 PATTERN (insn) = gen_cbranchhi4_real (cmp, OP (2), OP (1), OP (3));
2885 else
2886 PATTERN (insn) = gen_cbranchhi4_real_inverted (cmp, OP (2), OP (1), OP (3));
2888 MUST_BE_OK (insn);
2891 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2892 should be handled by the second alternative of the cbranchhi_real pattern. */
2893 if (rtx_equal_p (OP (1), OP (2)))
2895 OP (1) = OP (2) = BC;
2896 MUST_BE_OK (insn);
2899 tmp_id = get_max_insn_count ();
2900 saved_op1 = OP (1);
2902 OP (1) = move_to_acc (1, insn);
2904 MAYBE_OK (insn);
2906 /* If we omitted the move of OP1 into the accumulator (because
2907 it was already there from a previous insn), then force the
2908 generation of the move instruction now. We know that we
2909 are about to emit a move into HL via AX, and hence our
2910 optimization to remove the load of OP1 is no longer valid. */
2911 if (tmp_id == get_max_insn_count ())
2912 force_into_acc (saved_op1, insn);
2914 /* We have to copy op2 to HL, but that involves the acc, which
2915 already has a live value. Emit it before those insns. */
2916 if (prev)
2917 first = next_nonnote_nondebug_insn (prev);
2918 else
2919 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2921 OP (2) = move_to_hl (2, first);
2923 MUST_BE_OK (insn);
2926 /* Like op2, but AX = A op X. */
2928 static void
2929 rl78_alloc_physical_registers_umul (rtx insn)
2931 rtx prev = prev_nonnote_nondebug_insn (insn);
2932 rtx first;
2933 int tmp_id;
2934 rtx saved_op1;
2936 OP (0) = transcode_memory_rtx (OP (0), BC, insn);
2937 OP (1) = transcode_memory_rtx (OP (1), DE, insn);
2938 OP (2) = transcode_memory_rtx (OP (2), HL, insn);
2940 MAYBE_OK (insn);
2942 if (recog_data.constraints[1][0] == '%'
2943 && is_virtual_register (OP (1))
2944 && !is_virtual_register (OP (2))
2945 && !CONSTANT_P (OP (2)))
2947 rtx tmp = OP (1);
2948 OP (1) = OP (2);
2949 OP (2) = tmp;
2952 OP (0) = move_from_acc (0, insn);
2954 tmp_id = get_max_insn_count ();
2955 saved_op1 = OP (1);
2957 OP (1) = move_to_acc (1, insn);
2959 MAYBE_OK (insn);
2961 /* If we omitted the move of OP1 into the accumulator (because
2962 it was already there from a previous insn), then force the
2963 generation of the move instruction now. We know that we
2964 are about to emit a move into HL (or DE) via AX, and hence
2965 our optimization to remove the load of OP1 is no longer valid. */
2966 if (tmp_id == get_max_insn_count ())
2967 force_into_acc (saved_op1, insn);
2969 /* We have to copy op2 to X, but that involves the acc, which
2970 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_x (2, first);
2979 MUST_BE_OK (insn);
2982 static void
2983 rl78_alloc_address_registers_macax (rtx insn)
2985 int which, op;
2986 bool replace_in_op0 = false;
2987 bool replace_in_op1 = false;
2989 MAYBE_OK (insn);
2991 /* Two different MEMs are not allowed. */
2992 which = 0;
2993 for (op = 2; op >= 0; op --)
2995 if (MEM_P (OP (op)))
2997 if (op == 0 && replace_in_op0)
2998 continue;
2999 if (op == 1 && replace_in_op1)
3000 continue;
3002 switch (which)
3004 case 0:
3005 /* If we replace a MEM, make sure that we replace it for all
3006 occurrences of the same MEM in the insn. */
3007 replace_in_op0 = (op > 0 && rtx_equal_p (OP (op), OP (0)));
3008 replace_in_op1 = (op > 1 && rtx_equal_p (OP (op), OP (1)));
3010 OP (op) = transcode_memory_rtx (OP (op), HL, insn);
3011 if (op == 2
3012 && MEM_P (OP (op))
3013 && (REGNO (XEXP (OP (op), 0)) == SP_REG
3014 || (GET_CODE (XEXP (OP (op), 0)) == PLUS
3015 && REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
3017 emit_insn_before (gen_movhi (HL, gen_rtx_REG (HImode, SP_REG)), insn);
3018 OP (op) = replace_rtx (OP (op), gen_rtx_REG (HImode, SP_REG), HL);
3020 if (replace_in_op0)
3021 OP (0) = OP (op);
3022 if (replace_in_op1)
3023 OP (1) = OP (op);
3024 break;
3025 case 1:
3026 OP (op) = transcode_memory_rtx (OP (op), DE, insn);
3027 break;
3028 case 2:
3029 OP (op) = transcode_memory_rtx (OP (op), BC, insn);
3030 break;
3032 which ++;
3035 MUST_BE_OK (insn);
3038 /* Scan all insns and devirtualize them. */
3039 static void
3040 rl78_alloc_physical_registers (void)
3042 /* During most of the compile, gcc is dealing with virtual
3043 registers. At this point, we need to assign physical registers
3044 to the vitual ones, and copy in/out as needed. */
3046 rtx insn, curr;
3047 enum attr_valloc valloc_method;
3049 for (insn = get_insns (); insn; insn = curr)
3051 int i;
3053 curr = next_nonnote_nondebug_insn (insn);
3055 if (INSN_P (insn)
3056 && (GET_CODE (PATTERN (insn)) == SET
3057 || GET_CODE (PATTERN (insn)) == CALL)
3058 && INSN_CODE (insn) == -1)
3060 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
3061 continue;
3062 i = recog (PATTERN (insn), insn, 0);
3063 if (i == -1)
3065 debug_rtx (insn);
3066 gcc_unreachable ();
3068 INSN_CODE (insn) = i;
3072 cfun->machine->virt_insns_ok = 0;
3073 cfun->machine->real_insns_ok = 1;
3075 clear_content_memory ();
3077 for (insn = get_insns (); insn; insn = curr)
3079 rtx pattern;
3081 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
3083 if (!INSN_P (insn))
3085 if (LABEL_P (insn))
3086 clear_content_memory ();
3088 continue;
3091 if (dump_file)
3092 fprintf (dump_file, "Converting insn %d\n", INSN_UID (insn));
3094 pattern = PATTERN (insn);
3095 if (GET_CODE (pattern) == PARALLEL)
3096 pattern = XVECEXP (pattern, 0, 0);
3097 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3098 clear_content_memory ();
3099 if (GET_CODE (pattern) != SET
3100 && GET_CODE (pattern) != CALL)
3101 continue;
3102 if (GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
3103 continue;
3105 valloc_method = get_attr_valloc (insn);
3107 PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
3109 if (valloc_method == VALLOC_MACAX)
3111 record_content (AX, NULL_RTX);
3112 record_content (BC, NULL_RTX);
3113 record_content (DE, NULL_RTX);
3116 if (insn_ok_now (insn))
3117 continue;
3119 INSN_CODE (insn) = -1;
3121 if (RTX_FRAME_RELATED_P (insn))
3122 virt_insn_was_frame = 1;
3123 else
3124 virt_insn_was_frame = 0;
3126 switch (valloc_method)
3128 case VALLOC_OP1:
3129 rl78_alloc_physical_registers_op1 (insn);
3130 break;
3131 case VALLOC_OP2:
3132 rl78_alloc_physical_registers_op2 (insn);
3133 break;
3134 case VALLOC_RO1:
3135 rl78_alloc_physical_registers_ro1 (insn);
3136 break;
3137 case VALLOC_CMP:
3138 rl78_alloc_physical_registers_cmp (insn);
3139 break;
3140 case VALLOC_UMUL:
3141 rl78_alloc_physical_registers_umul (insn);
3142 break;
3143 case VALLOC_MACAX:
3144 /* Macro that clobbers AX. */
3145 rl78_alloc_address_registers_macax (insn);
3146 record_content (AX, NULL_RTX);
3147 record_content (BC, NULL_RTX);
3148 record_content (DE, NULL_RTX);
3149 break;
3152 if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
3153 clear_content_memory ();
3154 else
3155 process_postponed_content_update ();
3157 #if DEBUG_ALLOC
3158 fprintf (stderr, "\033[0m");
3159 #endif
3162 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3163 This function scans for uses of registers; the last use (i.e. first
3164 encounter when scanning backwards) triggers a REG_DEAD note if the
3165 reg was previously in DEAD[]. */
3166 static void
3167 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
3169 const char *fmt;
3170 int i, r;
3171 enum rtx_code code;
3173 if (!s)
3174 return;
3176 code = GET_CODE (s);
3178 switch (code)
3180 /* Compare registers by number. */
3181 case REG:
3182 r = REGNO (s);
3183 if (dump_file)
3185 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
3186 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
3187 print_rtl_single (dump_file, s);
3189 if (dead [r])
3190 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
3191 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
3192 dead [r + i] = 0;
3193 return;
3195 /* These codes have no constituent expressions
3196 and are unique. */
3197 case SCRATCH:
3198 case CC0:
3199 case PC:
3200 return;
3202 case CONST_INT:
3203 case CONST_VECTOR:
3204 case CONST_DOUBLE:
3205 case CONST_FIXED:
3206 /* These are kept unique for a given value. */
3207 return;
3209 default:
3210 break;
3213 fmt = GET_RTX_FORMAT (code);
3215 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3217 if (fmt[i] == 'E')
3219 int j;
3220 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
3221 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
3223 else if (fmt[i] == 'e')
3224 rl78_note_reg_uses (dead, XEXP (s, i), insn);
3228 /* Like the previous function, but scan for SETs instead. */
3229 static void
3230 rl78_note_reg_set (char *dead, rtx d, rtx insn)
3232 int r, i;
3234 if (GET_CODE (d) != REG)
3235 return;
3237 r = REGNO (d);
3238 if (dead [r])
3239 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
3240 if (dump_file)
3241 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
3242 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
3243 dead [r + i] = 1;
3246 /* This is a rather crude register death pass. Death status is reset
3247 at every jump or call insn. */
3248 static void
3249 rl78_calculate_death_notes (void)
3251 char dead[FIRST_PSEUDO_REGISTER];
3252 rtx insn, p, s, d;
3253 int i;
3255 memset (dead, 0, sizeof (dead));
3257 for (insn = get_last_insn ();
3258 insn;
3259 insn = prev_nonnote_nondebug_insn (insn))
3261 if (dump_file)
3263 fprintf (dump_file, "\n--------------------------------------------------");
3264 fprintf (dump_file, "\nDead:");
3265 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3266 if (dead[i])
3267 fprintf (dump_file, " %s", reg_names[i]);
3268 fprintf (dump_file, "\n");
3269 print_rtl_single (dump_file, insn);
3272 switch (GET_CODE (insn))
3274 case INSN:
3275 p = PATTERN (insn);
3276 switch (GET_CODE (p))
3278 case SET:
3279 s = SET_SRC (p);
3280 d = SET_DEST (p);
3281 rl78_note_reg_set (dead, d, insn);
3282 rl78_note_reg_uses (dead, s, insn);
3283 break;
3285 case USE:
3286 rl78_note_reg_uses (dead, p, insn);
3287 break;
3289 default:
3290 break;
3292 break;
3294 case JUMP_INSN:
3295 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
3297 memset (dead, 1, sizeof (dead));
3298 /* We expect a USE just prior to this, which will mark
3299 the actual return registers. The USE will have a
3300 death note, but we aren't going to be modifying it
3301 after this pass. */
3302 break;
3304 case CALL_INSN:
3305 memset (dead, 0, sizeof (dead));
3306 break;
3308 default:
3309 break;
3311 if (dump_file)
3312 print_rtl_single (dump_file, insn);
3316 /* Helper function to reset the origins in RP and the age in AGE for
3317 all registers. */
3318 static void
3319 reset_origins (int *rp, int *age)
3321 int i;
3322 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3324 rp[i] = i;
3325 age[i] = 0;
3329 /* The idea behind this optimization is to look for cases where we
3330 move data from A to B to C, and instead move from A to B, and A to
3331 C. If B is a virtual register or memory, this is a big win on its
3332 own. If B turns out to be unneeded after this, it's a bigger win.
3333 For each register, we try to determine where it's value originally
3334 came from, if it's propogated purely through moves (and not
3335 computes). The ORIGINS[] array has the regno for the "origin" of
3336 the value in the [regno] it's indexed by. */
3337 static void
3338 rl78_propogate_register_origins (void)
3340 int origins[FIRST_PSEUDO_REGISTER];
3341 int age[FIRST_PSEUDO_REGISTER];
3342 int i;
3343 rtx insn, ninsn = NULL_RTX;
3344 rtx pat;
3346 reset_origins (origins, age);
3348 for (insn = get_insns (); insn; insn = ninsn)
3350 ninsn = next_nonnote_nondebug_insn (insn);
3352 if (dump_file)
3354 fprintf (dump_file, "\n");
3355 fprintf (dump_file, "Origins:");
3356 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
3357 if (origins[i] != i)
3358 fprintf (dump_file, " r%d=r%d", i, origins[i]);
3359 fprintf (dump_file, "\n");
3360 print_rtl_single (dump_file, insn);
3363 switch (GET_CODE (insn))
3365 case CODE_LABEL:
3366 case BARRIER:
3367 case CALL_INSN:
3368 case JUMP_INSN:
3369 reset_origins (origins, age);
3370 break;
3372 default:
3373 break;
3375 case INSN:
3376 pat = PATTERN (insn);
3378 if (GET_CODE (pat) == PARALLEL)
3380 rtx clobber = XVECEXP (pat, 0, 1);
3381 pat = XVECEXP (pat, 0, 0);
3382 if (GET_CODE (clobber) == CLOBBER)
3384 int cr = REGNO (XEXP (clobber, 0));
3385 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
3386 if (dump_file)
3387 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
3388 for (i = 0; i < mb; i++)
3390 origins[cr + i] = cr + i;
3391 age[cr + i] = 0;
3394 else
3395 break;
3398 if (GET_CODE (pat) == SET)
3400 rtx src = SET_SRC (pat);
3401 rtx dest = SET_DEST (pat);
3402 int mb = GET_MODE_SIZE (GET_MODE (dest));
3404 if (GET_CODE (dest) == REG)
3406 int dr = REGNO (dest);
3408 if (GET_CODE (src) == REG)
3410 int sr = REGNO (src);
3411 int same = 1;
3412 int best_age, best_reg;
3414 /* See if the copy is not needed. */
3415 for (i = 0; i < mb; i ++)
3416 if (origins[dr + i] != origins[sr + i])
3417 same = 0;
3418 if (same)
3420 if (dump_file)
3421 fprintf (dump_file, "deleting because dest already has correct value\n");
3422 delete_insn (insn);
3423 break;
3426 if (dr < 8 || sr >= 8)
3428 int ar;
3430 best_age = -1;
3431 best_reg = -1;
3432 /* See if the copy can be made from another
3433 bank 0 register instead, instead of the
3434 virtual src register. */
3435 for (ar = 0; ar < 8; ar += mb)
3437 same = 1;
3438 for (i = 0; i < mb; i ++)
3439 if (origins[ar + i] != origins[sr + i])
3440 same = 0;
3442 /* The chip has some reg-reg move limitations. */
3443 if (mb == 1 && dr > 3)
3444 same = 0;
3446 if (same)
3448 if (best_age == -1 || best_age > age[sr + i])
3450 best_age = age[sr + i];
3451 best_reg = sr;
3456 if (best_reg != -1)
3458 /* FIXME: copy debug info too. */
3459 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
3460 sr = best_reg;
3464 for (i = 0; i < mb; i++)
3466 origins[dr + i] = origins[sr + i];
3467 age[dr + i] = age[sr + i] + 1;
3470 else
3472 /* The destination is computed, its origin is itself. */
3473 if (dump_file)
3474 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
3475 dr, mb, mb == 1 ? "" : "s");
3476 for (i = 0; i < mb; i ++)
3478 origins[dr + i] = dr + i;
3479 age[dr + i] = 0;
3483 /* Any registers marked with that reg as an origin are reset. */
3484 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3485 if (origins[i] >= dr && origins[i] < dr + mb)
3487 origins[i] = i;
3488 age[i] = 0;
3492 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3493 if (get_attr_valloc (insn) == VALLOC_MACAX)
3495 if (dump_file)
3496 fprintf (dump_file, "Resetting origin of AX/BC for macro.\n");
3497 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3498 if (i <= 3 || origins[i] <= 3)
3500 origins[i] = i;
3501 age[i] = 0;
3505 if (GET_CODE (src) == ASHIFT
3506 || GET_CODE (src) == ASHIFTRT
3507 || GET_CODE (src) == LSHIFTRT)
3509 rtx count = XEXP (src, 1);
3510 if (GET_CODE (count) == REG)
3512 /* Special case - our pattern clobbers the count register. */
3513 int r = REGNO (count);
3514 if (dump_file)
3515 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
3516 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3517 if (i == r || origins[i] == r)
3519 origins[i] = i;
3520 age[i] = 0;
3529 /* Remove any SETs where the destination is unneeded. */
3530 static void
3531 rl78_remove_unused_sets (void)
3533 rtx insn, ninsn = NULL_RTX;
3534 rtx dest;
3536 for (insn = get_insns (); insn; insn = ninsn)
3538 ninsn = next_nonnote_nondebug_insn (insn);
3540 if ((insn = single_set (insn)) == NULL_RTX)
3541 continue;
3543 dest = SET_DEST (insn);
3545 if (GET_CODE (dest) != REG || REGNO (dest) > 23)
3546 continue;
3548 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
3549 delete_insn (insn);
3553 /* This is the top of the devritualization pass. */
3554 static void
3555 rl78_reorg (void)
3557 /* split2 only happens when optimizing, but we need all movSIs to be
3558 split now. */
3559 if (optimize <= 0)
3560 split_all_insns ();
3562 rl78_alloc_physical_registers ();
3564 if (dump_file)
3566 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3567 print_rtl_with_bb (dump_file, get_insns (), 0);
3570 rl78_propogate_register_origins ();
3571 rl78_calculate_death_notes ();
3573 if (dump_file)
3575 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3576 print_rtl_with_bb (dump_file, get_insns (), 0);
3577 fprintf (dump_file, "\n======================================================================\n");
3580 rl78_remove_unused_sets ();
3582 /* The code after devirtualizing has changed so much that at this point
3583 we might as well just rescan everything. Note that
3584 df_rescan_all_insns is not going to help here because it does not
3585 touch the artificial uses and defs. */
3586 df_finish_pass (true);
3587 if (optimize > 1)
3588 df_live_add_problem ();
3589 df_scan_alloc (NULL);
3590 df_scan_blocks ();
3592 if (optimize)
3593 df_analyze ();
3596 #undef TARGET_RETURN_IN_MEMORY
3597 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3599 static bool
3600 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3602 const HOST_WIDE_INT size = int_size_in_bytes (type);
3603 return (size == -1 || size > 8);
3607 #undef TARGET_RTX_COSTS
3608 #define TARGET_RTX_COSTS rl78_rtx_costs
3610 static bool rl78_rtx_costs (rtx x,
3611 int code,
3612 int outer_code ATTRIBUTE_UNUSED,
3613 int opno ATTRIBUTE_UNUSED,
3614 int * total,
3615 bool speed ATTRIBUTE_UNUSED)
3617 if (code == IF_THEN_ELSE)
3618 return COSTS_N_INSNS (10);
3619 if (GET_MODE (x) == SImode)
3621 switch (code)
3623 case MULT:
3624 if (RL78_MUL_RL78)
3625 *total = COSTS_N_INSNS (14);
3626 else if (RL78_MUL_G13)
3627 *total = COSTS_N_INSNS (29);
3628 else
3629 *total = COSTS_N_INSNS (500);
3630 return true;
3631 case PLUS:
3632 *total = COSTS_N_INSNS (8);
3633 return true;
3634 case ASHIFT:
3635 case ASHIFTRT:
3636 case LSHIFTRT:
3637 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3639 switch (INTVAL (XEXP (x, 1)))
3641 case 0: *total = COSTS_N_INSNS (0); break;
3642 case 1: *total = COSTS_N_INSNS (6); break;
3643 case 2: case 3: case 4: case 5: case 6: case 7:
3644 *total = COSTS_N_INSNS (10); break;
3645 case 8: *total = COSTS_N_INSNS (6); break;
3646 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3647 *total = COSTS_N_INSNS (10); break;
3648 case 16: *total = COSTS_N_INSNS (3); break;
3649 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3650 *total = COSTS_N_INSNS (4); break;
3651 case 24: *total = COSTS_N_INSNS (4); break;
3652 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3653 *total = COSTS_N_INSNS (5); break;
3656 else
3657 *total = COSTS_N_INSNS (10+4*16);
3658 return true;
3661 return false;
3665 #undef TARGET_UNWIND_WORD_MODE
3666 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3668 static enum machine_mode
3669 rl78_unwind_word_mode (void)
3671 return HImode;
3674 struct gcc_target targetm = TARGET_INITIALIZER;
3676 #include "gt-rl78.h"