1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011 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)
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/>. */
23 #include "coretypes.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
32 #include "insn-attr.h"
39 #include "diagnostic-core.h"
47 #include "target-def.h"
48 #include "langhooks.h"
49 #include "rl78-protos.h"
50 #include "tree-pass.h"
52 static inline bool is_interrupt_func (const_tree decl);
53 static inline bool is_brk_interrupt_func (const_tree decl);
54 static void rl78_reorg (void);
57 /* Debugging statements are tagged with DEBUG0 only so that they can
58 be easily enabled individually, by replacing the '0' with '1' as
63 /* REGISTER_NAMES has the names for individual 8-bit registers, but
64 these have the names we need to use when referring to 16-bit
66 static const char * const word_regnames[] =
68 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
69 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
70 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
71 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
72 "sp", "ap", "psw", "es", "cs"
75 struct GTY(()) machine_function
77 /* If set, the rest of the fields have been computed. */
79 /* Which register pairs need to be pushed in the prologue. */
80 int need_to_push [FIRST_PSEUDO_REGISTER / 2];
82 /* These fields describe the frame layout... */
84 /* 4 bytes for saved PC */
88 int framesize_outgoing;
92 /* If set, recog is allowed to match against the "real" patterns. */
94 /* If set, recog is allowed to match against the "virtual" patterns. */
96 /* Set if the current function needs to clean up any trampolines. */
100 /* This is our init_machine_status, as set in
101 rl78_option_override. */
102 static struct machine_function *
103 rl78_init_machine_status (void)
105 struct machine_function *m;
107 m = ggc_alloc_cleared_machine_function ();
108 m->virt_insns_ok = 1;
113 /* Returns whether to run the devirtualization pass. */
120 /* Runs the devirtualization pass. */
128 /* This pass converts virtual instructions using virtual registers, to
129 real instructions using real registers. Rather than run it as
130 reorg, we reschedule it before vartrack to help with debugging. */
131 static struct opt_pass rl78_devirt_pass =
146 static struct register_pass_info rl78_devirt_info =
151 PASS_POS_INSERT_BEFORE
154 #undef TARGET_ASM_FILE_START
155 #define TARGET_ASM_FILE_START rl78_asm_file_start
158 rl78_asm_file_start (void)
162 for (i = 0; i < 8; i++)
164 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 8 + i, 0xffef0 + i);
165 fprintf (asm_out_file, "r%d\t=\t0x%x\n", 16 + i, 0xffee8 + i);
168 register_pass (& rl78_devirt_info);
172 #undef TARGET_OPTION_OVERRIDE
173 #define TARGET_OPTION_OVERRIDE rl78_option_override
176 rl78_option_override (void)
178 flag_omit_frame_pointer = 1;
179 flag_no_function_cse = 1;
180 flag_split_wide_types = 0;
182 init_machine_status = rl78_init_machine_status;
185 /* Most registers are 8 bits. Some are 16 bits because, for example,
186 gcc doesn't like dealing with $FP as a register pair. This table
187 maps register numbers to size in bytes. */
188 static const int register_sizes[] =
190 1, 1, 1, 1, 1, 1, 1, 1,
191 1, 1, 1, 1, 1, 1, 1, 1,
192 1, 1, 1, 1, 1, 1, 2, 1,
193 1, 1, 1, 1, 1, 1, 1, 1,
197 /* Predicates used in the MD patterns. This one is true when virtual
198 insns may be matched, which typically means before (or during) the
201 rl78_virt_insns_ok (void)
204 return cfun->machine->virt_insns_ok;
208 /* Predicates used in the MD patterns. This one is true when real
209 insns may be matched, which typically means after (or during) the
212 rl78_real_insns_ok (void)
215 return cfun->machine->real_insns_ok;
219 /* Implements HARD_REGNO_NREGS. */
221 rl78_hard_regno_nregs (int regno, enum machine_mode mode)
223 int rs = register_sizes[regno];
226 return ((GET_MODE_SIZE (mode) + rs - 1) / rs);
229 /* Implements HARD_REGNO_MODE_OK. */
231 rl78_hard_regno_mode_ok (int regno, enum machine_mode mode)
233 int s = GET_MODE_SIZE (mode);
237 /* These are not to be used by gcc. */
238 if (regno == 23 || regno == ES_REG || regno == CS_REG)
240 /* $fp can alway sbe accessed as a 16-bit value. */
241 if (regno == FP_REG && s == 2)
245 /* Since a reg-reg move is really a reg-mem move, we must
246 enforce alignment. */
247 if (s > 1 && (regno % 2))
252 return (mode == BImode);
253 /* All other registers must be accessed in their natural sizes. */
254 if (s == register_sizes [regno])
259 /* Simplify_gen_subreg() doesn't handle memory references the way we
260 need it to below, so we use this function for when we must get a
261 valid subreg in a "natural" state. */
263 rl78_subreg (enum machine_mode mode, rtx r, enum machine_mode omode, int byte)
265 if (GET_CODE (r) == MEM)
266 return adjust_address (r, mode, byte);
268 return simplify_gen_subreg (mode, r, omode, byte);
271 /* Used by movsi. Split SImode moves into two HImode moves, using
272 appropriate patterns for the upper and lower halves of symbols. */
274 rl78_expand_movsi (rtx *operands)
276 rtx op00, op02, op10, op12;
278 op00 = rl78_subreg (HImode, operands[0], SImode, 0);
279 op02 = rl78_subreg (HImode, operands[0], SImode, 2);
280 if (GET_CODE (operands[1]) == CONST
281 || GET_CODE (operands[1]) == SYMBOL_REF)
283 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
284 op10 = gen_rtx_CONST (HImode, op10);
285 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
286 op12 = gen_rtx_CONST (HImode, op12);
290 op10 = rl78_subreg (HImode, operands[1], SImode, 0);
291 op12 = rl78_subreg (HImode, operands[1], SImode, 2);
294 if (rtx_equal_p (operands[0], operands[1]))
296 else if (rtx_equal_p (op00, op12))
298 emit_move_insn (op02, op12);
299 emit_move_insn (op00, op10);
303 emit_move_insn (op00, op10);
304 emit_move_insn (op02, op12);
308 /* Used by various two-operand expanders which cannot accept all
309 operands in the "far" namespace. Force some such operands into
310 registers so that each pattern has at most one far operand. */
312 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
317 /* FIXME: in the future, be smarter about only doing this if the
318 other operand is also far, assuming the devirtualizer can also
320 if (rl78_far_p (operands[0]))
322 temp_reg = operands[0];
323 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
329 emit_insn (gen (operands[0], operands[1]));
331 emit_move_insn (temp_reg, operands[0]);
335 /* Likewise, but for three-operand expanders. */
337 rl78_force_nonfar_3 (rtx *operands, rtx (*gen)(rtx,rtx,rtx))
342 /* FIXME: Likewise. */
343 if (rl78_far_p (operands[1]))
345 rtx temp_reg = gen_reg_rtx (GET_MODE (operands[1]));
346 emit_move_insn (temp_reg, operands[1]);
347 operands[1] = temp_reg;
350 if (rl78_far_p (operands[0]))
352 temp_reg = operands[0];
353 operands[0] = gen_reg_rtx (GET_MODE (operands[0]));
359 emit_insn (gen (operands[0], operands[1], operands[2]));
361 emit_move_insn (temp_reg, operands[0]);
365 #undef TARGET_CAN_ELIMINATE
366 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
369 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
374 /* Returns nonzero if the given register needs to be saved by the
377 need_to_save (int regno)
379 if (is_interrupt_func (cfun->decl))
382 return 1; /* don't know what devirt will need */
384 return 0; /* don't need to save interrupt registers */
385 if (current_function_is_leaf)
387 return df_regs_ever_live_p (regno);
392 if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
394 if (fixed_regs[regno])
396 if (crtl->calls_eh_return)
398 if (df_regs_ever_live_p (regno)
399 && !call_used_regs[regno])
404 /* We use this to wrap all emitted insns in the prologue. */
408 RTX_FRAME_RELATED_P (x) = 1;
412 /* Compute all the frame-related fields in our machine_function
415 rl78_compute_frame_info (void)
419 cfun->machine->computed = 1;
420 cfun->machine->framesize_regs = 0;
421 cfun->machine->framesize_locals = get_frame_size ();
422 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
424 for (i = 0; i < 16; i ++)
425 if (need_to_save (i * 2) || need_to_save (i * 2 + 1))
427 cfun->machine->need_to_push [i] = 1;
428 cfun->machine->framesize_regs += 2;
431 cfun->machine->need_to_push [i] = 0;
433 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
434 cfun->machine->framesize_locals ++;
436 cfun->machine->framesize = (cfun->machine->framesize_regs
437 + cfun->machine->framesize_locals
438 + cfun->machine->framesize_outgoing);
441 /* Returns true if the provided function has the specified attribute. */
443 has_func_attr (const_tree decl, const char * func_attr)
445 if (decl == NULL_TREE)
446 decl = current_function_decl;
448 return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
451 /* Returns true if the provided function has the "interrupt" attribute. */
453 is_interrupt_func (const_tree decl)
455 return has_func_attr (decl, "interrupt") || has_func_attr (decl, "brk_interrupt");
458 /* Returns true if the provided function has the "brk_interrupt" attribute. */
460 is_brk_interrupt_func (const_tree decl)
462 return has_func_attr (decl, "brk_interrupt");
465 /* Check "interrupt" attributes. */
467 rl78_handle_func_attribute (tree * node,
470 int flags ATTRIBUTE_UNUSED,
473 gcc_assert (DECL_P (* node));
474 gcc_assert (args == NULL_TREE);
476 if (TREE_CODE (* node) != FUNCTION_DECL)
478 warning (OPT_Wattributes, "%qE attribute only applies to functions",
480 * no_add_attrs = true;
483 /* FIXME: We ought to check that the interrupt and exception
484 handler attributes have been applied to void functions. */
488 #undef TARGET_ATTRIBUTE_TABLE
489 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
491 /* Table of RL78-specific attributes. */
492 const struct attribute_spec rl78_attribute_table[] =
494 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
495 affects_type_identity. */
496 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
498 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute,
500 { NULL, 0, 0, false, false, false, NULL, false }
505 /* Break down an address RTX into its component base/index/addend
506 portions and return TRUE if the address is of a valid form, else
509 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
515 if (GET_CODE (x) == REG)
521 /* We sometimes get these without the CONST wrapper */
522 if (GET_CODE (x) == PLUS
523 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
524 && GET_CODE (XEXP (x, 1)) == CONST_INT)
530 if (GET_CODE (x) == PLUS)
535 if (GET_CODE (*base) != REG
536 && GET_CODE (x) == REG)
543 if (GET_CODE (*base) != REG)
546 if (GET_CODE (x) == ZERO_EXTEND
547 && GET_CODE (XEXP (x, 0)) == REG)
549 *index = XEXP (x, 0);
554 switch (GET_CODE (x))
557 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
558 && GET_CODE (XEXP (x, 0)) == CONST_INT)
581 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
584 rl78_hl_b_c_addr_p (rtx op)
588 if (GET_CODE (op) != PLUS)
592 if (GET_CODE (hl) == ZERO_EXTEND)
598 if (GET_CODE (hl) != REG)
600 if (GET_CODE (bc) != ZERO_EXTEND)
603 if (GET_CODE (bc) != REG)
605 if (REGNO (hl) != HL_REG)
607 if (REGNO (bc) != B_REG && REGNO (bc) != C_REG)
613 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
615 /* Used in various constraints and predicates to match operands in the
616 "far" address space. */
620 if (GET_CODE (x) != MEM)
623 fprintf(stderr, "\033[35mrl78_far_p: "); debug_rtx(x);
624 fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
626 return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
629 /* Return the appropriate mode for a named address pointer. */
630 #undef TARGET_ADDR_SPACE_POINTER_MODE
631 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
632 static enum machine_mode
633 rl78_addr_space_pointer_mode (addr_space_t addrspace)
637 case ADDR_SPACE_GENERIC:
646 /* Return the appropriate mode for a named address address. */
647 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
648 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
649 static enum machine_mode
650 rl78_addr_space_address_mode (addr_space_t addrspace)
654 case ADDR_SPACE_GENERIC:
663 #undef TARGET_LEGITIMATE_CONSTANT_P
664 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
667 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED)
672 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
673 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
676 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
677 bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
679 rtx base, index, addend;
681 if (as == ADDR_SPACE_GENERIC
682 && GET_MODE (x) == SImode)
685 if (! characterize_address (x, &base, &index, &addend))
690 int ir = REGNO (index);
691 int br = REGNO (base);
693 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
694 OK (REG_IS (br, HL_REG) && REG_IS (ir, B_REG), "[hl+b]");
695 OK (REG_IS (br, HL_REG) && REG_IS (ir, C_REG), "[hl+c]");
699 if (strict && base && GET_CODE (base) == REG && REGNO (base) >= FIRST_PSEUDO_REGISTER)
705 /* Determine if one named address space is a subset of another. */
706 #undef TARGET_ADDR_SPACE_SUBSET_P
707 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
709 rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
711 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
712 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
714 if (subset == superset)
718 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
721 #undef TARGET_ADDR_SPACE_CONVERT
722 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
723 /* Convert from one address space to another. */
725 rl78_addr_space_convert (rtx op, tree from_type, tree to_type)
727 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
728 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
731 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
732 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
734 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
736 /* This is unpredictable, as we're truncating off usable address
739 result = gen_reg_rtx (HImode);
740 emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
743 else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
745 /* This always works. */
746 result = gen_reg_rtx (SImode);
749 emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op);
750 emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx);
757 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
759 rl78_regno_mode_code_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
760 addr_space_t address_space ATTRIBUTE_UNUSED,
761 int outer_code ATTRIBUTE_UNUSED, int index_code)
763 if (regno < 24 && regno >= 16)
765 if (index_code == REG)
766 return (regno == HL_REG);
767 if (regno == C_REG || regno == B_REG || regno == E_REG || regno == L_REG)
772 /* Implements MODE_CODE_BASE_REG_CLASS. */
774 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
775 addr_space_t address_space ATTRIBUTE_UNUSED,
776 int outer_code ATTRIBUTE_UNUSED,
777 int index_code ATTRIBUTE_UNUSED)
782 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
783 described in the machine_Function struct definition, above. */
785 rl78_initial_elimination_offset (int from, int to)
787 int rv = 0; /* as if arg to arg */
789 rl78_compute_frame_info ();
793 case STACK_POINTER_REGNUM:
794 rv += cfun->machine->framesize_outgoing;
795 rv += cfun->machine->framesize_locals;
797 case FRAME_POINTER_REGNUM:
798 rv += cfun->machine->framesize_regs;
807 case FRAME_POINTER_REGNUM:
809 rv -= cfun->machine->framesize_regs;
810 case ARG_POINTER_REGNUM:
819 /* Expand the function prologue (from the prologue pattern). */
821 rl78_expand_prologue (void)
824 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
827 if (!cfun->machine->computed)
828 rl78_compute_frame_info ();
830 for (i = 0; i < 16; i++)
831 if (cfun->machine->need_to_push [i])
836 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
839 F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
842 emit_insn (gen_sel_rb (GEN_INT (0)));
844 if (frame_pointer_needed)
845 F (emit_move_insn (gen_rtx_REG (HImode, FRAME_POINTER_REGNUM),
846 gen_rtx_REG (HImode, STACK_POINTER_REGNUM)));
848 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
851 int fs_byte = (fs > 254) ? 254 : fs;
852 F (emit_insn (gen_subhi3 (sp, sp, GEN_INT (fs_byte))));
857 /* Expand the function epilogue (from the epilogue pattern). */
859 rl78_expand_epilogue (void)
862 rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
865 if (frame_pointer_needed)
867 emit_move_insn (gen_rtx_REG (HImode, STACK_POINTER_REGNUM),
868 gen_rtx_REG (HImode, FRAME_POINTER_REGNUM));
872 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
875 int fs_byte = (fs > 254) ? 254 : fs;
877 emit_insn (gen_addhi3 (sp, sp, GEN_INT (fs_byte)));
882 for (i = 15; i >= 0; i--)
883 if (cfun->machine->need_to_push [i])
885 int need_bank = i / 4;
889 emit_insn (gen_sel_rb (GEN_INT (need_bank)));
892 emit_insn (gen_pop (gen_rtx_REG (HImode, i * 2)));
896 emit_insn (gen_sel_rb (GEN_INT (0)));
898 if (cfun->machine->trampolines_used)
899 emit_insn (gen_trampoline_uninit ());
901 if (is_brk_interrupt_func (cfun->decl))
902 emit_jump_insn (gen_brk_interrupt_return ());
903 else if (is_interrupt_func (cfun->decl))
904 emit_jump_insn (gen_interrupt_return ());
906 emit_jump_insn (gen_rl78_return ());
909 /* Likewise, for exception handlers. */
911 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED)
913 /* FIXME - replace this with an indirect jump with stack adjust. */
914 emit_jump_insn (gen_rl78_return ());
917 #undef TARGET_ASM_FUNCTION_PROLOGUE
918 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
920 /* We don't use this to actually emit the function prologue. We use
921 this to insert a comment in the asm file describing the
924 rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
928 if (cfun->machine->framesize == 0)
930 fprintf (file, "\t; start of function\n");
932 if (cfun->machine->framesize_regs)
934 fprintf (file, "\t; push %d:", cfun->machine->framesize_regs);
935 for (i = 0; i < 16; i ++)
936 if (cfun->machine->need_to_push[i])
937 fprintf (file, " %s", word_regnames[i*2]);
941 if (frame_pointer_needed)
942 fprintf (file, "\t; $fp points here (r22)\n");
944 if (cfun->machine->framesize_locals)
945 fprintf (file, "\t; locals: %d byte%s\n", cfun->machine->framesize_locals,
946 cfun->machine->framesize_locals == 1 ? "" : "s");
948 if (cfun->machine->framesize_outgoing)
949 fprintf (file, "\t; outgoing: %d byte%s\n", cfun->machine->framesize_outgoing,
950 cfun->machine->framesize_outgoing == 1 ? "" : "s");
953 /* Return an RTL describing where a function return value of type RET_TYPE
956 #undef TARGET_FUNCTION_VALUE
957 #define TARGET_FUNCTION_VALUE rl78_function_value
960 rl78_function_value (const_tree ret_type,
961 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
962 bool outgoing ATTRIBUTE_UNUSED)
964 enum machine_mode mode = TYPE_MODE (ret_type);
966 return gen_rtx_REG (mode, 8);
969 #undef TARGET_PROMOTE_FUNCTION_MODE
970 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
972 static enum machine_mode
973 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
974 enum machine_mode mode,
975 int *punsignedp ATTRIBUTE_UNUSED,
976 const_tree funtype ATTRIBUTE_UNUSED, int for_return ATTRIBUTE_UNUSED)
981 /* Return an RTL expression describing the register holding a function
982 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
983 be passed on the stack. CUM describes the previous parameters to the
984 function and NAMED is false if the parameter is part of a variable
985 parameter list, or the last named parameter before the start of a
986 variable parameter list. */
988 #undef TARGET_FUNCTION_ARG
989 #define TARGET_FUNCTION_ARG rl78_function_arg
992 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
993 enum machine_mode mode ATTRIBUTE_UNUSED,
994 const_tree type ATTRIBUTE_UNUSED,
995 bool named ATTRIBUTE_UNUSED)
1000 #undef TARGET_FUNCTION_ARG_ADVANCE
1001 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1004 rl78_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, const_tree type,
1005 bool named ATTRIBUTE_UNUSED)
1008 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
1010 rounded_size = ((mode == BLKmode)
1011 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1012 if (rounded_size & 1)
1014 (*cum) += rounded_size;
1017 #undef TARGET_FUNCTION_ARG_BOUNDARY
1018 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1021 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
1022 const_tree type ATTRIBUTE_UNUSED)
1027 /* Supported modifier letters:
1029 A - address of a MEM
1030 S - SADDR form of a real register
1031 v - real register corresponding to a virtual register
1032 m - minus - negative of CONST_INT value.
1033 c - inverse of a conditional (NE vs EQ for example)
1035 h - bottom HI of an SI
1037 q - bottom QI of an HI
1039 e - third QI of an SI (i.e. where the ES register gets values from)
1043 /* Implements the bulk of rl78_print_operand, below. We do it this
1044 way because we need to test for a constant at the top level and
1045 insert the '#', but not test for it anywhere else as we recurse
1046 down into the operand. */
1048 rl78_print_operand_1 (FILE * file, rtx op, int letter)
1052 switch (GET_CODE (op))
1056 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1059 if (rl78_far_p (op))
1060 fprintf(file, "es:");
1063 op = adjust_address (op, HImode, 2);
1068 op = adjust_address (op, HImode, 0);
1073 op = adjust_address (op, QImode, 1);
1078 op = adjust_address (op, QImode, 0);
1083 op = adjust_address (op, QImode, 2);
1086 if (CONSTANT_P (XEXP (op, 0)))
1089 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1091 else if (GET_CODE (XEXP (op, 0)) == PLUS
1092 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF)
1095 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1097 else if (GET_CODE (XEXP (op, 0)) == PLUS
1098 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
1099 && REGNO (XEXP (XEXP (op, 0), 0)) == 2)
1101 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u');
1103 rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0);
1109 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1117 fprintf (file, "%s", reg_names [REGNO (op) | 1]);
1118 else if (letter == 'H')
1119 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1120 else if (letter == 'q')
1121 fprintf (file, "%s", reg_names [REGNO (op) & ~1]);
1122 else if (letter == 'e')
1123 fprintf (file, "%s", reg_names [REGNO (op) + 2]);
1124 else if (letter == 'S')
1125 fprintf (file, "0x%x", 0xffef8 + REGNO (op));
1126 else if (GET_MODE (op) == HImode
1127 && ! (REGNO (op) & ~0xfe))
1130 fprintf (file, "%s", word_regnames [REGNO (op) % 8]);
1132 fprintf (file, "%s", word_regnames [REGNO (op)]);
1135 fprintf (file, "%s", reg_names [REGNO (op)]);
1140 fprintf (file, "%ld", INTVAL (op) >> 8);
1141 else if (letter == 'H')
1142 fprintf (file, "%ld", INTVAL (op) >> 16);
1143 else if (letter == 'q')
1144 fprintf (file, "%ld", INTVAL (op) & 0xff);
1145 else if (letter == 'h')
1146 fprintf (file, "%ld", INTVAL (op) & 0xffff);
1147 else if (letter == 'e')
1148 fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff);
1149 else if (letter == 'm')
1150 fprintf (file, "%ld", - INTVAL (op));
1152 fprintf(file, "%ld", INTVAL (op));
1156 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1161 int bits = INTVAL (XEXP (op, 1));
1162 int ofs = INTVAL (XEXP (op, 2));
1163 if (bits == 16 && ofs == 0)
1164 fprintf (file, "%%lo16(");
1165 else if (bits == 16 && ofs == 16)
1166 fprintf (file, "%%hi16(");
1167 else if (bits == 8 && ofs == 16)
1168 fprintf (file, "%%hi8(");
1171 rl78_print_operand_1 (file, XEXP (op, 0), 0);
1172 fprintf (file, ")");
1177 if (GET_CODE (XEXP (op, 0)) == REG)
1178 fprintf (file, "%s", reg_names [REGNO (XEXP (op, 0))]);
1180 print_rtl (file, op);
1187 fprintf (file, "%%hi16(");
1193 fprintf (file, "%%lo16(");
1199 fprintf (file, "%%hi8(");
1203 if (letter == 'q' || letter == 'Q')
1204 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1206 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND)
1208 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1209 fprintf (file, "+");
1210 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1214 rl78_print_operand_1 (file, XEXP (op, 0), letter);
1215 fprintf (file, "+");
1216 rl78_print_operand_1 (file, XEXP (op, 1), letter);
1219 fprintf (file, ")");
1226 fprintf (file, "%%hi16(");
1232 fprintf (file, "%%lo16(");
1238 fprintf (file, "%%hi8(");
1242 if (letter == 'q' || letter == 'Q')
1243 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1245 output_addr_const (file, op);
1247 fprintf (file, ")");
1252 output_asm_label (op);
1256 fprintf (file, letter == 'c' ? "nc" : "c");
1259 fprintf (file, letter == 'c' ? "h" : "nh");
1262 fprintf (file, letter == 'c' ? "c" : "nc");
1265 fprintf (file, letter == 'c' ? "nh" : "h");
1268 fprintf (file, letter == 'c' ? "nz" : "z");
1271 fprintf (file, letter == 'c' ? "z" : "nz");
1275 fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op)));
1280 #undef TARGET_PRINT_OPERAND
1281 #define TARGET_PRINT_OPERAND rl78_print_operand
1284 rl78_print_operand (FILE * file, rtx op, int letter)
1286 if (CONSTANT_P (op) && letter != 'u')
1287 fprintf (file, "#");
1288 rl78_print_operand_1 (file, op, letter);
1291 #undef TARGET_TRAMPOLINE_INIT
1292 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1294 /* Note that the RL78's addressing makes it very difficult to do
1295 trampolines on the stack. So, libgcc has a small pool of
1296 trampolines from which one is allocated to this task. */
1298 rl78_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
1300 rtx mov_addr, thunk_addr;
1301 rtx function = XEXP (DECL_RTL (fndecl), 0);
1303 mov_addr = adjust_address (m_tramp, HImode, 0);
1304 thunk_addr = gen_reg_rtx (HImode);
1306 function = force_reg (HImode, function);
1307 static_chain = force_reg (HImode, static_chain);
1309 emit_insn (gen_trampoline_init (thunk_addr, function, static_chain));
1310 emit_move_insn (mov_addr, thunk_addr);
1312 cfun->machine->trampolines_used = 1;
1315 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1316 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1319 rl78_trampoline_adjust_address (rtx m_tramp)
1321 rtx x = gen_rtx_MEM (HImode, m_tramp);
1325 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1326 the "normal" compares, specifically, it only has unsigned compares,
1327 so we must synthesize the missing ones. */
1329 rl78_expand_compare (rtx *operands)
1331 /* RL78 does not have signed comparisons. We must modify the
1332 operands to be in the unsigned range, and emit an unsigned
1335 enum machine_mode mode;
1340 switch (GET_CODE (operands[0]))
1359 fprintf (stderr, "\033[38;5;129mrl78_expand_compare\n");
1360 debug_rtx (operands[0]);
1361 fprintf (stderr, "\033[0m");
1364 mode = GET_MODE (operands[1]);
1365 if (mode == VOIDmode)
1366 mode = GET_MODE (operands[2]);
1367 high_bit = GEN_INT (~0 << (GET_MODE_BITSIZE (mode) - 1));
1369 /* 0: conditional 1,2: operands */
1370 for (i = 1; i <= 2; i ++)
1372 rtx r = operands[i];
1374 if (GET_CODE (r) == CONST_INT)
1375 r = GEN_INT (INTVAL (r) ^ INTVAL (high_bit));
1378 r = gen_rtx_PLUS (mode, operands[i], high_bit);
1379 r = copy_to_mode_reg (mode, r);
1384 operands[0] = gen_rtx_fmt_ee (new_cond, GET_MODE (operands[0]), operands[1], operands[2]);
1387 fprintf (stderr, "\033[38;5;142mrl78_expand_compare\n");
1388 debug_rtx (operands[0]);
1389 fprintf (stderr, "\033[0m");
1395 /* Define this to 1 if you are debugging the peephole optimizers. */
1396 #define DEBUG_PEEP 0
1398 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1399 The default "word" size is a byte so we can effectively use all the
1400 registers, but we want to do 16-bit moves whenever possible. This
1401 function determines when such a move is an option. */
1403 rl78_peep_movhi_p (rtx *operands)
1408 /* (set (op0) (op1))
1409 (set (op2) (op3)) */
1412 fprintf (stderr, "\033[33m");
1413 debug_rtx(operands[0]);
1414 debug_rtx(operands[1]);
1415 debug_rtx(operands[2]);
1416 debug_rtx(operands[3]);
1417 fprintf (stderr, "\033[0m");
1420 if (rtx_equal_p (operands[0], operands[3]))
1423 fprintf (stderr, "no peep: overlapping\n");
1428 for (i = 0; i < 2; i ++)
1430 if (GET_CODE (operands[i]) != GET_CODE (operands[i+2]))
1433 fprintf (stderr, "no peep: different codes\n");
1437 if (GET_MODE (operands[i]) != GET_MODE (operands[i+2]))
1440 fprintf (stderr, "no peep: different modes\n");
1445 switch (GET_CODE (operands[i]))
1449 if (REGNO (operands[i]) + 1 != REGNO (operands[i+2])
1450 || GET_MODE (operands[i]) != QImode)
1453 fprintf (stderr, "no peep: wrong regnos %d %d %d\n",
1454 REGNO (operands[i]), REGNO (operands[i+2]),
1459 if (! rl78_hard_regno_mode_ok (REGNO (operands[i]), HImode))
1462 fprintf (stderr, "no peep: reg %d not HI\n", REGNO (operands[i]));
1472 if (GET_MODE (operands[i]) != QImode)
1474 if (MEM_ALIGN (operands[i]) < 16)
1476 a = XEXP (operands[i], 0);
1477 if (GET_CODE (a) == CONST)
1479 if (GET_CODE (a) == PLUS)
1481 if (GET_CODE (a) == CONST_INT
1485 fprintf (stderr, "no peep: misaligned mem %d\n", i);
1486 debug_rtx (operands[i]);
1490 m = adjust_address (operands[i], QImode, 1);
1491 if (! rtx_equal_p (m, operands[i+2]))
1494 fprintf (stderr, "no peep: wrong mem %d\n", i);
1496 debug_rtx (operands[i+2]);
1504 fprintf (stderr, "no peep: wrong rtx %d\n", i);
1510 fprintf (stderr, "\033[32mpeep!\033[0m\n");
1515 /* Likewise, when a peephole is activated, this function helps compute
1516 the new operands. */
1518 rl78_setup_peep_movhi (rtx *operands)
1522 for (i = 0; i < 2; i ++)
1524 switch (GET_CODE (operands[i]))
1527 operands[i+4] = gen_rtx_REG (HImode, REGNO (operands[i]));
1531 operands[i+4] = GEN_INT ((INTVAL (operands[i]) & 0xff) + ((char)INTVAL (operands[i+2])) * 256);
1535 operands[i+4] = adjust_address (operands[i], HImode, 0);
1545 How Devirtualization works in the RL78 GCC port
1549 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1550 bytes of register space, in four banks, memory-mapped. One bank is
1551 the "selected" bank and holds the registers used for primary
1552 operations. Since the registers are memory mapped, often you can
1553 still refer to the unselected banks via memory accesses.
1557 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1558 and refers to the other banks via their memory addresses, although
1559 they're treated as regular registers internally. These "virtual"
1560 registers are R8 through R23 (bank3 is reserved for asm-based
1561 interrupt handlers).
1563 There are four machine description files:
1565 rl78.md - common register-independent patterns and definitions
1566 rl78-expand.md - expanders
1567 rl78-virt.md - patterns that match BEFORE devirtualization
1568 rl78-real.md - patterns that match AFTER devirtualization
1570 At least through register allocation and reload, gcc is told that it
1571 can do pretty much anything - but may only use the virtual registers.
1572 GCC cannot properly create the varying addressing modes that the RL78
1573 supports in an efficient way.
1575 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1576 uses the "valloc" attribute in rl78-virt.md for determining the rules
1577 by which it will replace virtual registers with real registers (or
1578 not) and how to make up addressing modes. For example, insns tagged
1579 with "ro1" have a single read-only parameter, which may need to be
1580 moved from memory/constant/vreg to a suitable real register. As part
1581 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1582 patterns and enabling the rl78-real.md patterns. The new patterns'
1583 constraints are used to determine the real registers used. NOTE:
1584 patterns in rl78-virt.md essentially ignore the constrains and rely on
1585 predicates, where the rl78-real.md ones essentially ignore the
1586 predicates and rely on the constraints.
1588 The devirtualization pass is scheduled via the pass manager (despite
1589 being called "rl78_reorg") so it can be scheduled prior to var-track
1590 (the idea is to let gdb know about the new registers). Ideally, it
1591 would be scheduled right after pro/epilogue generation, so the
1592 post-reload optimizers could operate on the real registers, but when I
1593 tried that there were some issues building the target libraries.
1595 During devirtualization, a simple register move optimizer is run. It
1596 would be better to run a full CSE/propogation pass on it through, or
1597 re-run regmove, but that has not yet been attempted.
1600 #define DEBUG_ALLOC 0
1602 /* Rescans an insn to see if it's recognized again. This is done
1603 carefully to ensure that all the constraint information is accurate
1604 for the newly matched insn. */
1606 insn_ok_now (rtx insn)
1608 INSN_CODE (insn) = -1;
1609 if (recog (PATTERN (insn), insn, 0) > -1)
1611 extract_insn (insn);
1612 if (constrain_operands (1))
1615 fprintf (stderr, "\033[32m");
1617 fprintf (stderr, "\033[0m");
1624 fprintf (stderr, "\033[41;30m Unrecognized insn \033[0m\n");
1629 fprintf (stderr, "\033[31m");
1631 fprintf (stderr, "\033[0m");
1637 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
1638 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
1639 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
1640 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
1644 #define FAILED gcc_unreachable ()
1645 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
1648 /* Registers into which we move the contents of virtual registers. */
1649 #define X gen_rtx_REG (QImode, 0)
1650 #define A gen_rtx_REG (QImode, 1)
1651 #define C gen_rtx_REG (QImode, 2)
1652 #define B gen_rtx_REG (QImode, 3)
1653 #define E gen_rtx_REG (QImode, 4)
1654 #define D gen_rtx_REG (QImode, 5)
1655 #define L gen_rtx_REG (QImode, 6)
1656 #define H gen_rtx_REG (QImode, 7)
1658 #define AX gen_rtx_REG (HImode, 0)
1659 #define BC gen_rtx_REG (HImode, 2)
1660 #define DE gen_rtx_REG (HImode, 4)
1661 #define HL gen_rtx_REG (HImode, 6)
1663 #define OP(x) (*recog_data.operand_loc[x])
1665 /* Returns TRUE if R is a virtual register. */
1667 is_virtual_register (rtx r)
1669 return (GET_CODE (r) == REG
1674 /* In all these alloc routines, we expect the following: the insn
1675 pattern is unshared, the insn was previously recognized and failed
1676 due to predicates or constraints, and the operand data is in
1679 static int virt_insn_was_frame;
1681 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
1684 EM2 (int line ATTRIBUTE_UNUSED, rtx r)
1687 fprintf (stderr, "\033[36m%d: ", line);
1689 fprintf (stderr, "\033[0m");
1691 /*SCHED_GROUP_P (r) = 1;*/
1692 if (virt_insn_was_frame)
1693 RTX_FRAME_RELATED_P (r) = 1;
1697 #define EM(x) EM2 (__LINE__, x)
1699 /* Return a suitable RTX for the low half of a __far address. */
1701 rl78_lo16 (rtx addr)
1703 if (GET_CODE (addr) == SYMBOL_REF
1704 || GET_CODE (addr) == CONST)
1706 rtx r = gen_rtx_ZERO_EXTRACT (HImode, addr, GEN_INT (16), GEN_INT (0));
1707 r = gen_rtx_CONST (HImode, r);
1710 return rl78_subreg (HImode, addr, SImode, 0);
1713 /* Return a suitable RTX for the high half's lower byte of a __far address. */
1717 if (GET_CODE (addr) == SYMBOL_REF
1718 || GET_CODE (addr) == CONST)
1720 rtx r = gen_rtx_ZERO_EXTRACT (QImode, addr, GEN_INT (8), GEN_INT (16));
1721 r = gen_rtx_CONST (QImode, r);
1724 return rl78_subreg (QImode, addr, SImode, 2);
1727 /* Copy any register values into real registers and return an RTX for
1728 the same memory, now addressed by real registers. Any needed insns
1729 are emitted before BEFORE. */
1731 transcode_memory_rtx (rtx m, rtx newbase, rtx before)
1733 rtx base, index, addendr;
1736 if (GET_CODE (m) != MEM)
1739 if (GET_MODE (XEXP (m, 0)) == SImode)
1741 rtx seg = rl78_hi8 (XEXP (m, 0));
1743 fprintf (stderr, "setting ES:\n");
1746 emit_insn_before (EM(gen_movqi (A, seg)), before);
1747 emit_insn_before (EM(gen_movqi_es (A)), before);
1748 m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
1751 characterize_address (XEXP (m, 0), &base, &index, &addendr);
1752 gcc_assert (index == NULL_RTX);
1755 fprintf (stderr, "\033[33m"); debug_rtx(m); fprintf (stderr, "\033[0m");
1758 if (base == NULL_RTX)
1761 if (addendr && GET_CODE (addendr) == CONST_INT)
1762 addend = INTVAL (addendr);
1764 if (REGNO (base) == SP_REG)
1766 if (addend >= 0 && addend <= 255)
1770 /* BASE should be a virtual register. We copy it to NEWBASE. If
1771 the addend is out of range for DE/HL, we use AX to compute the full
1775 || (addend > 255 && REGNO (newbase) != 2)
1776 || (addendr && GET_CODE (addendr) != CONST_INT))
1781 EM (emit_insn_before (gen_movhi (AX, base), before));
1782 EM (emit_insn_before (gen_addhi3 (AX, AX, addendr), before));
1783 EM (emit_insn_before (gen_movhi (newbase, AX), before));
1789 EM (emit_insn_before (gen_movhi (newbase, base), before));
1794 base = gen_rtx_PLUS (HImode, base, GEN_INT (addend));
1797 fprintf (stderr, "\033[33m");
1800 m = change_address (m, GET_MODE (m), base);
1803 fprintf (stderr, "\033[0m");
1808 /* Copy SRC to accumulator (A or AX), placing any generated insns
1809 before BEFORE. Returns accumulator RTX. */
1812 move_to_acc (int opno, rtx before)
1815 enum machine_mode mode = GET_MODE (src);
1817 if (GET_CODE (src) == REG
1821 if (mode == VOIDmode)
1822 mode = recog_data.operand_mode[opno];
1826 EM (emit_insn_before (gen_movqi (A, src), before));
1831 EM (emit_insn_before (gen_movhi (AX, src), before));
1836 /* Copy accumulator (A or AX) to DEST, placing any generated insns
1837 after AFTER. Returns accumulator RTX. */
1840 move_from_acc (rtx dest, rtx after)
1842 enum machine_mode mode = GET_MODE (dest);
1844 if (REG_P (dest) && REGNO (dest) < 2)
1849 EM (emit_insn_after (gen_movqi (dest, A), after));
1854 EM (emit_insn_after (gen_movhi (dest, AX), after));
1859 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
1860 before BEFORE. Returns reg RTX. */
1863 move_acc_to_reg (rtx acc, int regno, rtx before)
1865 enum machine_mode mode = GET_MODE (acc);
1868 reg = gen_rtx_REG (mode, regno);
1872 EM (emit_insn_before (gen_movqi (reg, A), before));
1877 EM (emit_insn_before (gen_movhi (reg, AX), before));
1882 /* Copy SRC to X, placing any generated insns before BEFORE.
1886 move_to_x (int opno, rtx before)
1889 enum machine_mode mode = GET_MODE (src);
1892 if (mode == VOIDmode)
1893 mode = recog_data.operand_mode[opno];
1894 reg = (mode == QImode) ? X : AX;
1896 if (mode == QImode || ! is_virtual_register (OP (opno)))
1898 OP(opno) = move_to_acc (opno, before);
1899 OP(opno) = move_acc_to_reg (OP(opno), X_REG, before);
1904 EM (emit_insn_before (gen_movqi (reg, src), before));
1906 EM (emit_insn_before (gen_movhi (reg, src), before));
1911 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
1912 Returns H/HL RTX. */
1915 move_to_hl (int opno, rtx before)
1917 rtx src = OP (opno);
1918 enum machine_mode mode = GET_MODE (src);
1921 if (mode == VOIDmode)
1922 mode = recog_data.operand_mode[opno];
1923 reg = (mode == QImode) ? L : HL;
1925 if (mode == QImode || ! is_virtual_register (OP (opno)))
1927 OP (opno) = move_to_acc (opno, before);
1928 OP (opno) = move_acc_to_reg (OP (opno), L_REG, before);
1933 EM (emit_insn_before (gen_movqi (reg, src), before));
1935 EM (emit_insn_before (gen_movhi (reg, src), before));
1940 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
1941 Returns E/DE RTX. */
1944 move_to_de (int opno, rtx before)
1946 rtx src = OP (opno);
1947 enum machine_mode mode = GET_MODE (src);
1950 if (mode == VOIDmode)
1951 mode = recog_data.operand_mode[opno];
1953 reg = (mode == QImode) ? E : DE;
1955 if (mode == QImode || ! is_virtual_register (OP (opno)))
1957 OP (opno) = move_to_acc (opno, before);
1958 OP (opno) = move_acc_to_reg (OP (opno), E_REG, before);
1962 rtx move = mode == QImode ? gen_movqi (reg, src) : gen_movhi (reg, src);
1964 EM (emit_insn_before (move, before));
1970 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
1972 rl78_alloc_physical_registers_op1 (rtx insn)
1974 /* op[0] = func op[1] */
1976 /* We first try using A as the destination, then copying it
1978 if (rtx_equal_p (OP(0), OP(1)))
1981 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
1985 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
1986 OP(1) = transcode_memory_rtx (OP(1), HL, insn);
1991 OP(0) = move_from_acc (OP(0), insn);
1995 /* Try copying the src to acc first, then. This is for, for
1996 example, ZERO_EXTEND or NOT. */
1997 OP(1) = move_to_acc (1, insn);
2004 /* Devirtualize an insn of the form (SET (op) (unop (op) (op))). */
2006 rl78_alloc_physical_registers_op2 (rtx insn)
2008 /* op[0] = op[1] func op[2] */
2009 rtx prev = prev_nonnote_nondebug_insn (insn);
2013 if (rtx_equal_p (OP(0), OP(1)))
2016 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2017 prev = next_nonnote_nondebug_insn (prev);
2018 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2019 prev = prev_nonnote_nondebug_insn (prev);
2021 else if (rtx_equal_p (OP(0), OP(2)))
2023 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2024 prev = next_nonnote_nondebug_insn (prev);
2026 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2027 prev = prev_nonnote_nondebug_insn (prev);
2031 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2032 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2033 prev = next_nonnote_nondebug_insn (prev);
2034 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2039 prev = prev_nonnote_nondebug_insn (insn);
2040 if (recog_data.constraints[1][0] == '%'
2041 && is_virtual_register (OP (1))
2042 && ! is_virtual_register (OP (2))
2043 && ! CONSTANT_P (OP (2)))
2050 /* Make a note of wether (H)L is being used. It matters
2051 because if OP(2) alsoneeds reloading, then we must take
2052 care not to corrupt HL. */
2053 hl_used = reg_mentioned_p (L, OP (0)) || reg_mentioned_p (L, OP (1));
2055 OP(0) = move_from_acc (OP (0), insn);
2056 OP(1) = move_to_acc (1, insn);
2060 /* We have to copy op2 to HL, but that involves AX, which
2061 already has a live value. Emit it before those insns. */
2064 first = next_nonnote_nondebug_insn (prev);
2066 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2069 OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
2076 /* Devirtualize an insn of the form (SET () (unop (op))). */
2079 rl78_alloc_physical_registers_ro1 (rtx insn)
2082 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2086 OP(0) = move_to_acc (0, insn);
2093 /* Devirtualize a compare insn. */
2095 rl78_alloc_physical_registers_cmp (rtx insn)
2097 /* op[1] cmp_op[0] op[2] */
2098 rtx prev = prev_nonnote_nondebug_insn (insn);
2101 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2102 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2106 OP(1) = move_to_acc (1, insn);
2110 /* We have to copy op2 to HL, but that involves the acc, which
2111 already has a live value. Emit it before those insns. */
2114 first = next_nonnote_nondebug_insn (prev);
2116 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2118 OP(2) = move_to_hl (2, first);
2125 /* Like op2, but AX = A op X. */
2127 rl78_alloc_physical_registers_umul (rtx insn)
2129 /* op[0] = op[1] func op[2] */
2130 rtx prev = prev_nonnote_nondebug_insn (insn);
2133 OP(0) = transcode_memory_rtx (OP(0), BC, insn);
2134 OP(1) = transcode_memory_rtx (OP(1), DE, insn);
2135 OP(2) = transcode_memory_rtx (OP(2), HL, insn);
2139 if (recog_data.constraints[1][0] == '%'
2140 && is_virtual_register (OP(1))
2141 && !is_virtual_register (OP(2))
2142 && !CONSTANT_P (OP(2)))
2149 OP(0) = move_from_acc (OP(0), insn);
2150 OP(1) = move_to_acc (1, insn);
2154 /* We have to copy op2 to X, but that involves the acc, which
2155 already has a live value. Emit it before those insns. */
2158 first = next_nonnote_nondebug_insn (prev);
2160 for (first = insn; prev_nonnote_nondebug_insn (first); first = prev_nonnote_nondebug_insn (first))
2162 OP(2) = move_to_x (2, first);
2169 /* Scan all insns and devirtualize them. */
2171 rl78_alloc_physical_registers (void)
2173 /* During most of the compile, gcc is dealing with virtual
2174 registers. At this point, we need to assign physical registers
2175 to the vitual ones, and copy in/out as needed. */
2178 enum attr_valloc valloc_method;
2180 for (insn = get_insns (); insn; insn = curr)
2184 curr = next_nonnote_nondebug_insn (insn);
2187 && (GET_CODE (PATTERN (insn)) == SET
2188 || GET_CODE (PATTERN (insn)) == CALL)
2189 && INSN_CODE (insn) == -1)
2191 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2193 i = recog (PATTERN (insn), insn, 0);
2199 INSN_CODE (insn) = i;
2203 cfun->machine->virt_insns_ok = 0;
2204 cfun->machine->real_insns_ok = 1;
2206 for (insn = get_insns (); insn; insn = curr)
2208 curr = insn ? next_nonnote_nondebug_insn (insn) : NULL;
2212 if (GET_CODE (PATTERN (insn)) != SET
2213 && GET_CODE (PATTERN (insn)) != CALL)
2216 if (GET_CODE (SET_SRC (PATTERN (insn))) == ASM_OPERANDS)
2219 valloc_method = get_attr_valloc (insn);
2221 PATTERN (insn)= copy_rtx_if_shared (PATTERN (insn));
2223 if (insn_ok_now (insn))
2226 INSN_CODE (insn) = -1;
2228 if (RTX_FRAME_RELATED_P (insn))
2229 virt_insn_was_frame = 1;
2231 virt_insn_was_frame = 0;
2233 switch (valloc_method)
2236 rl78_alloc_physical_registers_op1 (insn);
2239 rl78_alloc_physical_registers_op2 (insn);
2242 rl78_alloc_physical_registers_ro1 (insn);
2245 rl78_alloc_physical_registers_cmp (insn);
2248 rl78_alloc_physical_registers_umul (insn);
2251 /* Macro that clobbers AX */
2256 fprintf (stderr, "\033[0m");
2260 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
2261 This function scans for uses of registers; the last use (i.e. first
2262 encounter when scanning backwards) triggers a REG_DEAD note if the
2263 reg was previously in DEAD[]. */
2265 rl78_note_reg_uses (char *dead, rtx s, rtx insn)
2274 code = GET_CODE (s);
2278 /* Compare registers by number. */
2283 fprintf (dump_file, "note use reg %d size %d on insn %d\n",
2284 r, GET_MODE_SIZE (GET_MODE (s)), INSN_UID (insn));
2285 print_rtl_single (dump_file, s);
2288 add_reg_note (insn, REG_DEAD, gen_rtx_REG (GET_MODE (s), r));
2289 for (i = 0; i < GET_MODE_SIZE (GET_MODE (s)); i ++)
2293 /* These codes have no constituent expressions
2304 /* These are kept unique for a given value. */
2311 fmt = GET_RTX_FORMAT (code);
2313 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2318 for (j = XVECLEN (s, i) - 1; j >= 0; j--)
2319 rl78_note_reg_uses (dead, XVECEXP (s, i, j), insn);
2321 else if (fmt[i] == 'e')
2322 rl78_note_reg_uses (dead, XEXP (s, i), insn);
2326 /* Like the previous function, but scan for SETs instead. */
2328 rl78_note_reg_set (char *dead, rtx d, rtx insn)
2332 if (GET_CODE (d) != REG)
2337 add_reg_note (insn, REG_UNUSED, gen_rtx_REG (GET_MODE (d), r));
2339 fprintf (dump_file, "note set reg %d size %d\n", r, GET_MODE_SIZE (GET_MODE (d)));
2340 for (i = 0; i < GET_MODE_SIZE (GET_MODE (d)); i ++)
2344 /* This is a rather crude register death pass. Death status is reset
2345 at every jump or call insn. */
2347 rl78_calculate_death_notes (void)
2349 char dead[FIRST_PSEUDO_REGISTER];
2353 memset (dead, 0, sizeof (dead));
2355 for (insn = get_last_insn ();
2357 insn = prev_nonnote_nondebug_insn (insn))
2361 fprintf (dump_file, "\n--------------------------------------------------");
2362 fprintf (dump_file, "\nDead:");
2363 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2365 fprintf(dump_file, " %s", reg_names[i]);
2366 fprintf (dump_file, "\n");
2367 print_rtl_single (dump_file, insn);
2370 switch (GET_CODE (insn))
2374 switch (GET_CODE (p))
2379 rl78_note_reg_set (dead, d, insn);
2380 rl78_note_reg_uses (dead, s, insn);
2384 rl78_note_reg_uses (dead, p, insn);
2393 if (INSN_CODE (insn) == CODE_FOR_rl78_return)
2395 memset (dead, 1, sizeof (dead));
2396 /* We expect a USE just prior to this, which will mark
2397 the actual return registers. The USE will have a
2398 death note, but we aren't going to be modifying it
2403 memset (dead, 0, sizeof (dead));
2410 print_rtl_single (dump_file, insn);
2414 /* Helper function to reset the origins in RP and the age in AGE for
2417 reset_origins (int *rp, int *age)
2420 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2427 /* The idea behind this optimization is to look for cases where we
2428 move data from A to B to C, and instead move from A to B, and A to
2429 C. If B is a virtual register or memory, this is a big win on its
2430 own. If B turns out to be unneeded after this, it's a bigger win.
2431 For each register, we try to determine where it's value originally
2432 came from, if it's propogated purely through moves (and not
2433 computes). The ORIGINS[] array has the regno for the "origin" of
2434 the value in the [regno] it's indexed by. */
2436 rl78_propogate_register_origins (void)
2438 int origins[FIRST_PSEUDO_REGISTER];
2439 int age[FIRST_PSEUDO_REGISTER];
2441 rtx insn, ninsn = NULL_RTX;
2444 reset_origins (origins, age);
2446 for (insn = get_insns (); insn; insn = ninsn)
2448 ninsn = next_nonnote_nondebug_insn (insn);
2452 fprintf (dump_file, "\n");
2453 fprintf (dump_file, "Origins:");
2454 for (i = 0; i < FIRST_PSEUDO_REGISTER; i ++)
2455 if (origins[i] != i)
2456 fprintf (dump_file, " r%d=r%d", i, origins[i]);
2457 fprintf (dump_file, "\n");
2458 print_rtl_single (dump_file, insn);
2461 switch (GET_CODE (insn))
2467 reset_origins (origins, age);
2474 pat = PATTERN (insn);
2476 if (GET_CODE (pat) == PARALLEL)
2478 rtx clobber = XVECEXP (pat, 0, 1);
2479 pat = XVECEXP (pat, 0, 0);
2480 if (GET_CODE (clobber) == CLOBBER)
2482 int cr = REGNO (XEXP (clobber, 0));
2483 int mb = GET_MODE_SIZE (GET_MODE (XEXP (clobber, 0)));
2485 fprintf (dump_file, "reset origins of %d regs at %d\n", mb, cr);
2486 for (i = 0; i < mb; i++)
2488 origins[cr + i] = cr + i;
2496 if (GET_CODE (pat) == SET)
2498 rtx src = SET_SRC (pat);
2499 rtx dest = SET_DEST (pat);
2500 int mb = GET_MODE_SIZE (GET_MODE (dest));
2502 if (GET_CODE (dest) == REG)
2504 int dr = REGNO (dest);
2506 if (GET_CODE (src) == REG)
2508 int sr = REGNO (src);
2510 int best_age, best_reg;
2512 /* See if the copy is not needed. */
2513 for (i = 0; i < mb; i ++)
2514 if (origins[dr + i] != origins[sr + i])
2519 fprintf (dump_file, "deleting because dest already has correct value\n");
2524 if (dr < 8 || sr >= 8)
2530 /* See if the copy can be made from another
2531 bank 0 register instead, instead of the
2532 virtual src register. */
2533 for (ar = 0; ar < 8; ar += mb)
2536 for (i = 0; i < mb; i ++)
2537 if (origins[ar + i] != origins[sr + i])
2540 /* The chip has some reg-reg move limitations. */
2541 if (mb == 1 && dr > 3)
2546 if (best_age == -1 || best_age > age[sr + i])
2548 best_age = age[sr + i];
2556 /* FIXME: copy debug info too. */
2557 SET_SRC (pat) = gen_rtx_REG (GET_MODE (src), best_reg);
2562 for (i = 0; i < mb; i++)
2564 origins[dr + i] = origins[sr + i];
2565 age[dr + i] = age[sr + i] + 1;
2570 /* The destination is computed, its origin is itself. */
2572 fprintf (dump_file, "resetting origin of r%d for %d byte%s\n",
2573 dr, mb, mb == 1 ? "" : "s");
2574 for (i = 0; i < mb; i ++)
2576 origins[dr + i] = dr + i;
2581 /* Any registers marked with that reg as an origin are reset. */
2582 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2583 if (origins[i] >= dr && origins[i] < dr + mb)
2590 /* Special case - our ADDSI3 macro uses AX */
2591 if (get_attr_valloc (insn) == VALLOC_MACAX)
2594 fprintf (dump_file, "Resetting origin of AX for macro.\n");
2595 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2596 if (i <= 1 || origins[i] <= 1)
2603 if (GET_CODE (src) == ASHIFT
2604 || GET_CODE (src) == ASHIFTRT
2605 || GET_CODE (src) == LSHIFTRT)
2607 rtx count = XEXP (src, 1);
2608 if (GET_CODE (count) == REG)
2610 /* Special case - our pattern clobbers the count register. */
2611 int r = REGNO (count);
2613 fprintf (dump_file, "Resetting origin of r%d for shift.\n", r);
2614 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2615 if (i == r || origins[i] == r)
2627 /* Remove any SETs where the destination is unneeded. */
2629 rl78_remove_unused_sets (void)
2631 rtx insn, ninsn = NULL_RTX;
2634 for (insn = get_insns (); insn; insn = ninsn)
2636 ninsn = next_nonnote_nondebug_insn (insn);
2638 if ((insn = single_set (insn)) == NULL_RTX)
2641 dest = SET_DEST (insn);
2643 if (REGNO (dest) > 23)
2646 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
2651 #undef xTARGET_MACHINE_DEPENDENT_REORG
2652 #define xTARGET_MACHINE_DEPENDENT_REORG rl78_reorg
2654 /* This is the top of the devritualization pass. */
2658 rl78_alloc_physical_registers ();
2662 fprintf (dump_file, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
2663 print_rtl_with_bb (dump_file, get_insns ());
2666 rl78_propogate_register_origins ();
2667 rl78_calculate_death_notes ();
2671 fprintf (dump_file, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
2672 print_rtl_with_bb (dump_file, get_insns ());
2673 fprintf (dump_file, "\n======================================================================\n");
2676 rl78_remove_unused_sets ();
2678 /* The code after devirtualizing has changed so much that at this point
2679 we might as well just rescan everything. Note that
2680 df_rescan_all_insns is not going to help here because it does not
2681 touch the artificial uses and defs. */
2682 df_finish_pass (true);
2684 df_live_add_problem ();
2685 df_scan_alloc (NULL);
2692 #undef TARGET_RETURN_IN_MEMORY
2693 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
2696 rl78_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2698 const HOST_WIDE_INT size = int_size_in_bytes (type);
2699 return (size == -1 || size > 8);
2703 struct gcc_target targetm = TARGET_INITIALIZER;
2705 #include "gt-rl78.h"