1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2014 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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"
27 #include "stor-layout.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
35 #include "insn-attr.h"
44 #include "insn-codes.h"
48 #include "diagnostic-core.h"
51 #include "dominance.h"
57 #include "cfgcleanup.h"
59 #include "basic-block.h"
65 #include "target-def.h"
66 #include "langhooks.h"
67 #include "rl78-protos.h"
69 #include "tree-pass.h"
71 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
72 #include "insn-flags.h" /* for gen_*(). */
75 static inline bool is_interrupt_func (const_tree decl
);
76 static inline bool is_brk_interrupt_func (const_tree decl
);
77 static void rl78_reorg (void);
80 /* Debugging statements are tagged with DEBUG0 only so that they can
81 be easily enabled individually, by replacing the '0' with '1' as
86 /* REGISTER_NAMES has the names for individual 8-bit registers, but
87 these have the names we need to use when referring to 16-bit
89 static const char * const word_regnames
[] =
91 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
92 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
93 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
94 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
95 "sp", "ap", "psw", "es", "cs"
98 struct GTY(()) machine_function
100 /* If set, the rest of the fields have been computed. */
102 /* Which register pairs need to be pushed in the prologue. */
103 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
105 /* These fields describe the frame layout... */
107 /* 4 bytes for saved PC */
110 int framesize_locals
;
111 int framesize_outgoing
;
115 /* If set, recog is allowed to match against the "real" patterns. */
117 /* If set, recog is allowed to match against the "virtual" patterns. */
119 /* Set if the current function needs to clean up any trampolines. */
120 int trampolines_used
;
123 /* This is our init_machine_status, as set in
124 rl78_option_override. */
125 static struct machine_function
*
126 rl78_init_machine_status (void)
128 struct machine_function
*m
;
130 m
= ggc_cleared_alloc
<machine_function
> ();
131 m
->virt_insns_ok
= 1;
136 /* This pass converts virtual instructions using virtual registers, to
137 real instructions using real registers. Rather than run it as
138 reorg, we reschedule it before vartrack to help with debugging. */
141 const pass_data pass_data_rl78_devirt
=
145 OPTGROUP_NONE
, /* optinfo_flags */
146 TV_MACH_DEP
, /* tv_id */
147 0, /* properties_required */
148 0, /* properties_provided */
149 0, /* properties_destroyed */
150 0, /* todo_flags_start */
151 0, /* todo_flags_finish */
154 class pass_rl78_devirt
: public rtl_opt_pass
157 pass_rl78_devirt(gcc::context
*ctxt
)
158 : rtl_opt_pass(pass_data_rl78_devirt
, ctxt
)
162 /* opt_pass methods: */
163 virtual unsigned int execute (function
*)
174 make_pass_rl78_devirt (gcc::context
*ctxt
)
176 return new pass_rl78_devirt (ctxt
);
179 /* Redundant move elimination pass. Must be run after the basic block
180 reordering pass for the best effect. */
183 move_elim_pass (void)
185 rtx_insn
*insn
, *ninsn
;
188 for (insn
= get_insns (); insn
; insn
= ninsn
)
192 ninsn
= next_nonnote_nondebug_insn (insn
);
194 if ((set
= single_set (insn
)) == NULL_RTX
)
200 /* If we have two SET insns in a row (without anything
201 between them) and the source of the second one is the
202 destination of the first one, and vice versa, then we
203 can eliminate the second SET. */
205 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
206 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
210 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
221 print_rtl_with_bb (dump_file
, get_insns (), 0);
228 const pass_data pass_data_rl78_move_elim
=
231 "move_elim", /* name */
232 OPTGROUP_NONE
, /* optinfo_flags */
233 TV_MACH_DEP
, /* tv_id */
234 0, /* properties_required */
235 0, /* properties_provided */
236 0, /* properties_destroyed */
237 0, /* todo_flags_start */
238 0, /* todo_flags_finish */
241 class pass_rl78_move_elim
: public rtl_opt_pass
244 pass_rl78_move_elim(gcc::context
*ctxt
)
245 : rtl_opt_pass(pass_data_rl78_move_elim
, ctxt
)
249 /* opt_pass methods: */
250 virtual unsigned int execute (function
*) { return move_elim_pass (); }
256 make_pass_rl78_move_elim (gcc::context
*ctxt
)
258 return new pass_rl78_move_elim (ctxt
);
261 #undef TARGET_ASM_FILE_START
262 #define TARGET_ASM_FILE_START rl78_asm_file_start
265 rl78_asm_file_start (void)
271 /* The memory used is 0xffec8 to 0xffedf; real registers are in
272 0xffee0 to 0xffee7. */
273 for (i
= 8; i
< 32; i
++)
274 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
278 for (i
= 0; i
< 8; i
++)
280 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
281 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
282 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
286 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
287 static struct register_pass_info rl78_devirt_info
=
292 PASS_POS_INSERT_BEFORE
295 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
296 static struct register_pass_info rl78_move_elim_info
=
301 PASS_POS_INSERT_AFTER
304 register_pass (& rl78_devirt_info
);
305 register_pass (& rl78_move_elim_info
);
309 #undef TARGET_OPTION_OVERRIDE
310 #define TARGET_OPTION_OVERRIDE rl78_option_override
313 rl78_option_override (void)
315 flag_omit_frame_pointer
= 1;
316 flag_no_function_cse
= 1;
317 flag_split_wide_types
= 0;
319 init_machine_status
= rl78_init_machine_status
;
325 for (i
= 24; i
< 32; i
++)
330 /* Most registers are 8 bits. Some are 16 bits because, for example,
331 gcc doesn't like dealing with $FP as a register pair (the second
332 half of $fp is also 2 to keep reload happy wrt register pairs, but
333 no register class includes it). This table maps register numbers
335 static const int register_sizes
[] =
337 1, 1, 1, 1, 1, 1, 1, 1,
338 1, 1, 1, 1, 1, 1, 1, 1,
339 1, 1, 1, 1, 1, 1, 2, 2,
340 1, 1, 1, 1, 1, 1, 1, 1,
344 /* Predicates used in the MD patterns. This one is true when virtual
345 insns may be matched, which typically means before (or during) the
348 rl78_virt_insns_ok (void)
351 return cfun
->machine
->virt_insns_ok
;
355 /* Predicates used in the MD patterns. This one is true when real
356 insns may be matched, which typically means after (or during) the
359 rl78_real_insns_ok (void)
362 return cfun
->machine
->real_insns_ok
;
366 /* Implements HARD_REGNO_NREGS. */
368 rl78_hard_regno_nregs (int regno
, machine_mode mode
)
370 int rs
= register_sizes
[regno
];
373 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
376 /* Implements HARD_REGNO_MODE_OK. */
378 rl78_hard_regno_mode_ok (int regno
, machine_mode mode
)
380 int s
= GET_MODE_SIZE (mode
);
384 /* These are not to be used by gcc. */
385 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
387 /* $fp can always be accessed as a 16-bit value. */
388 if (regno
== FP_REG
&& s
== 2)
392 /* Since a reg-reg move is really a reg-mem move, we must
393 enforce alignment. */
394 if (s
> 1 && (regno
% 2))
399 return (mode
== BImode
);
400 /* All other registers must be accessed in their natural sizes. */
401 if (s
== register_sizes
[regno
])
406 /* Simplify_gen_subreg() doesn't handle memory references the way we
407 need it to below, so we use this function for when we must get a
408 valid subreg in a "natural" state. */
410 rl78_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
412 if (GET_CODE (r
) == MEM
)
413 return adjust_address (r
, mode
, byte
);
415 return simplify_gen_subreg (mode
, r
, omode
, byte
);
418 /* Used by movsi. Split SImode moves into two HImode moves, using
419 appropriate patterns for the upper and lower halves of symbols. */
421 rl78_expand_movsi (rtx
*operands
)
423 rtx op00
, op02
, op10
, op12
;
425 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
426 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
427 if (GET_CODE (operands
[1]) == CONST
428 || GET_CODE (operands
[1]) == SYMBOL_REF
)
430 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
431 op10
= gen_rtx_CONST (HImode
, op10
);
432 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
433 op12
= gen_rtx_CONST (HImode
, op12
);
437 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
438 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
441 if (rtx_equal_p (operands
[0], operands
[1]))
443 else if (rtx_equal_p (op00
, op12
))
445 emit_move_insn (op02
, op12
);
446 emit_move_insn (op00
, op10
);
450 emit_move_insn (op00
, op10
);
451 emit_move_insn (op02
, op12
);
455 /* Generate code to move an SImode value. */
457 rl78_split_movsi (rtx
*operands
)
459 rtx op00
, op02
, op10
, op12
;
461 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
462 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
464 if (GET_CODE (operands
[1]) == CONST
465 || GET_CODE (operands
[1]) == SYMBOL_REF
)
467 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
468 op10
= gen_rtx_CONST (HImode
, op10
);
469 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
470 op12
= gen_rtx_CONST (HImode
, op12
);
474 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
475 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
478 if (rtx_equal_p (operands
[0], operands
[1]))
480 else if (rtx_equal_p (op00
, op12
))
496 /* Used by various two-operand expanders which cannot accept all
497 operands in the "far" namespace. Force some such operands into
498 registers so that each pattern has at most one far operand. */
500 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
505 /* FIXME: in the future, be smarter about only doing this if the
506 other operand is also far, assuming the devirtualizer can also
508 if (rl78_far_p (operands
[0]))
510 temp_reg
= operands
[0];
511 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
517 emit_insn (gen (operands
[0], operands
[1]));
519 emit_move_insn (temp_reg
, operands
[0]);
523 /* Likewise, but for three-operand expanders. */
525 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
530 /* FIXME: Likewise. */
531 if (rl78_far_p (operands
[1]))
533 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
534 emit_move_insn (temp_reg
, operands
[1]);
535 operands
[1] = temp_reg
;
538 if (rl78_far_p (operands
[0]))
540 temp_reg
= operands
[0];
541 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
547 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
549 emit_move_insn (temp_reg
, operands
[0]);
553 #undef TARGET_CAN_ELIMINATE
554 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
557 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
562 /* Returns true if the given register needs to be saved by the
565 need_to_save (unsigned int regno
)
567 if (is_interrupt_func (cfun
->decl
))
569 /* We don't know what devirt will need */
573 /* We don't need to save registers that have
574 been reserved for interrupt handlers. */
578 /* If the handler is a non-leaf function then it may call
579 non-interrupt aware routines which will happily clobber
580 any call_used registers, so we have to preserve them. */
581 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
584 /* Otherwise we only have to save a register, call_used
585 or not, if it is used by this handler. */
586 return df_regs_ever_live_p (regno
);
589 if (regno
== FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
591 if (fixed_regs
[regno
])
593 if (crtl
->calls_eh_return
)
595 if (df_regs_ever_live_p (regno
)
596 && !call_used_regs
[regno
])
601 /* We use this to wrap all emitted insns in the prologue. */
605 RTX_FRAME_RELATED_P (x
) = 1;
609 /* Compute all the frame-related fields in our machine_function
612 rl78_compute_frame_info (void)
616 cfun
->machine
->computed
= 1;
617 cfun
->machine
->framesize_regs
= 0;
618 cfun
->machine
->framesize_locals
= get_frame_size ();
619 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
621 for (i
= 0; i
< 16; i
++)
622 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
624 cfun
->machine
->need_to_push
[i
] = 1;
625 cfun
->machine
->framesize_regs
+= 2;
628 cfun
->machine
->need_to_push
[i
] = 0;
630 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
631 cfun
->machine
->framesize_locals
++;
633 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
634 + cfun
->machine
->framesize_locals
635 + cfun
->machine
->framesize_outgoing
);
638 /* Returns true if the provided function has the specified attribute. */
640 has_func_attr (const_tree decl
, const char * func_attr
)
642 if (decl
== NULL_TREE
)
643 decl
= current_function_decl
;
645 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
648 /* Returns true if the provided function has the "interrupt" attribute. */
650 is_interrupt_func (const_tree decl
)
652 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
655 /* Returns true if the provided function has the "brk_interrupt" attribute. */
657 is_brk_interrupt_func (const_tree decl
)
659 return has_func_attr (decl
, "brk_interrupt");
662 /* Check "interrupt" attributes. */
664 rl78_handle_func_attribute (tree
* node
,
667 int flags ATTRIBUTE_UNUSED
,
670 gcc_assert (DECL_P (* node
));
671 gcc_assert (args
== NULL_TREE
);
673 if (TREE_CODE (* node
) != FUNCTION_DECL
)
675 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
677 * no_add_attrs
= true;
680 /* FIXME: We ought to check that the interrupt and exception
681 handler attributes have been applied to void functions. */
685 #undef TARGET_ATTRIBUTE_TABLE
686 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
688 /* Table of RL78-specific attributes. */
689 const struct attribute_spec rl78_attribute_table
[] =
691 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
692 affects_type_identity. */
693 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
695 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
697 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute
,
699 { NULL
, 0, 0, false, false, false, NULL
, false }
704 /* Break down an address RTX into its component base/index/addend
705 portions and return TRUE if the address is of a valid form, else
708 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
714 if (GET_CODE (x
) == UNSPEC
715 && XINT (x
, 1) == UNS_ES_ADDR
)
716 x
= XVECEXP (x
, 0, 1);
718 if (GET_CODE (x
) == REG
)
724 /* We sometimes get these without the CONST wrapper */
725 if (GET_CODE (x
) == PLUS
726 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
727 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
733 if (GET_CODE (x
) == PLUS
)
738 if (GET_CODE (*base
) != REG
739 && GET_CODE (x
) == REG
)
746 if (GET_CODE (*base
) != REG
)
749 if (GET_CODE (x
) == ZERO_EXTEND
750 && GET_CODE (XEXP (x
, 0)) == REG
)
752 *index
= XEXP (x
, 0);
757 switch (GET_CODE (x
))
760 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
761 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
784 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
787 rl78_hl_b_c_addr_p (rtx op
)
791 if (GET_CODE (op
) != PLUS
)
795 if (GET_CODE (hl
) == ZERO_EXTEND
)
801 if (GET_CODE (hl
) != REG
)
803 if (GET_CODE (bc
) != ZERO_EXTEND
)
806 if (GET_CODE (bc
) != REG
)
808 if (REGNO (hl
) != HL_REG
)
810 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
816 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
818 /* Used in various constraints and predicates to match operands in the
819 "far" address space. */
826 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx (x
);
827 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
829 return MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
;
832 /* Return the appropriate mode for a named address pointer. */
833 #undef TARGET_ADDR_SPACE_POINTER_MODE
834 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
836 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
840 case ADDR_SPACE_GENERIC
:
849 /* Returns TRUE for valid addresses. */
850 #undef TARGET_VALID_POINTER_MODE
851 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
853 rl78_valid_pointer_mode (machine_mode m
)
855 return (m
== HImode
|| m
== SImode
);
858 /* Return the appropriate mode for a named address address. */
859 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
860 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
862 rl78_addr_space_address_mode (addr_space_t addrspace
)
866 case ADDR_SPACE_GENERIC
:
875 #undef TARGET_LEGITIMATE_CONSTANT_P
876 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
879 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
884 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
885 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
888 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
889 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
891 rtx base
, index
, addend
;
892 bool is_far_addr
= false;
894 if (GET_CODE (x
) == UNSPEC
895 && XINT (x
, 1) == UNS_ES_ADDR
)
897 x
= XVECEXP (x
, 0, 1);
901 if (as
== ADDR_SPACE_GENERIC
902 && (GET_MODE (x
) == SImode
|| is_far_addr
))
905 if (! characterize_address (x
, &base
, &index
, &addend
))
908 /* We can't extract the high/low portions of a PLUS address
909 involving a register during devirtualization, so make sure all
910 such __far addresses do not have addends. This forces GCC to do
911 the sum separately. */
912 if (addend
&& base
&& as
== ADDR_SPACE_FAR
)
917 int ir
= REGNO (index
);
918 int br
= REGNO (base
);
920 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
921 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
922 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
926 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
929 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
930 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
936 /* Determine if one named address space is a subset of another. */
937 #undef TARGET_ADDR_SPACE_SUBSET_P
938 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
940 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
942 gcc_assert (subset
== ADDR_SPACE_GENERIC
|| subset
== ADDR_SPACE_FAR
);
943 gcc_assert (superset
== ADDR_SPACE_GENERIC
|| superset
== ADDR_SPACE_FAR
);
945 if (subset
== superset
)
949 return (subset
== ADDR_SPACE_GENERIC
&& superset
== ADDR_SPACE_FAR
);
952 #undef TARGET_ADDR_SPACE_CONVERT
953 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
954 /* Convert from one address space to another. */
956 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
958 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
959 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
962 gcc_assert (from_as
== ADDR_SPACE_GENERIC
|| from_as
== ADDR_SPACE_FAR
);
963 gcc_assert (to_as
== ADDR_SPACE_GENERIC
|| to_as
== ADDR_SPACE_FAR
);
965 if (to_as
== ADDR_SPACE_GENERIC
&& from_as
== ADDR_SPACE_FAR
)
967 /* This is unpredictable, as we're truncating off usable address
970 result
= gen_reg_rtx (HImode
);
971 emit_move_insn (result
, simplify_subreg (HImode
, op
, SImode
, 0));
974 else if (to_as
== ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_GENERIC
)
976 /* This always works. */
977 result
= gen_reg_rtx (SImode
);
978 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
979 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
986 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
988 rl78_regno_mode_code_ok_for_base_p (int regno
, machine_mode mode ATTRIBUTE_UNUSED
,
989 addr_space_t address_space ATTRIBUTE_UNUSED
,
990 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
992 if (regno
<= SP_REG
&& regno
>= 16)
994 if (index_code
== REG
)
995 return (regno
== HL_REG
);
996 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
1001 /* Implements MODE_CODE_BASE_REG_CLASS. */
1003 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED
,
1004 addr_space_t address_space ATTRIBUTE_UNUSED
,
1005 int outer_code ATTRIBUTE_UNUSED
,
1006 int index_code ATTRIBUTE_UNUSED
)
1011 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1012 described in the machine_Function struct definition, above. */
1014 rl78_initial_elimination_offset (int from
, int to
)
1016 int rv
= 0; /* as if arg to arg */
1018 rl78_compute_frame_info ();
1022 case STACK_POINTER_REGNUM
:
1023 rv
+= cfun
->machine
->framesize_outgoing
;
1024 rv
+= cfun
->machine
->framesize_locals
;
1026 case FRAME_POINTER_REGNUM
:
1027 rv
+= cfun
->machine
->framesize_regs
;
1036 case FRAME_POINTER_REGNUM
:
1038 rv
-= cfun
->machine
->framesize_regs
;
1039 case ARG_POINTER_REGNUM
:
1049 rl78_is_naked_func (void)
1051 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1054 /* Expand the function prologue (from the prologue pattern). */
1056 rl78_expand_prologue (void)
1059 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1062 if (rl78_is_naked_func ())
1065 /* Always re-compute the frame info - the register usage may have changed. */
1066 rl78_compute_frame_info ();
1068 if (flag_stack_usage_info
)
1069 current_function_static_stack_size
= cfun
->machine
->framesize
;
1071 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1072 for (i
= 0; i
< 4; i
++)
1073 if (cfun
->machine
->need_to_push
[i
])
1075 /* Select Bank 0 if we are using any registers from Bank 0. */
1076 emit_insn (gen_sel_rb (GEN_INT (0)));
1080 for (i
= 0; i
< 16; i
++)
1081 if (cfun
->machine
->need_to_push
[i
])
1085 emit_move_insn (gen_rtx_REG (HImode
, 0), gen_rtx_REG (HImode
, i
*2));
1086 F (emit_insn (gen_push (gen_rtx_REG (HImode
, 0))));
1090 int need_bank
= i
/4;
1092 if (need_bank
!= rb
)
1094 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1097 F (emit_insn (gen_push (gen_rtx_REG (HImode
, i
*2))));
1102 emit_insn (gen_sel_rb (GEN_INT (0)));
1104 if (frame_pointer_needed
)
1106 F (emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1107 gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
)));
1108 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
),
1109 gen_rtx_REG (HImode
, AX_REG
)));
1112 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1115 int fs_byte
= (fs
> 254) ? 254 : fs
;
1116 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1121 /* Expand the function epilogue (from the epilogue pattern). */
1123 rl78_expand_epilogue (void)
1126 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1129 if (rl78_is_naked_func ())
1132 if (frame_pointer_needed
)
1134 emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1135 gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1136 emit_move_insn (gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
),
1137 gen_rtx_REG (HImode
, AX_REG
));
1141 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1144 int fs_byte
= (fs
> 254) ? 254 : fs
;
1146 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1151 for (i
= 15; i
>= 0; i
--)
1152 if (cfun
->machine
->need_to_push
[i
])
1154 rtx dest
= gen_rtx_REG (HImode
, i
* 2);
1158 rtx ax
= gen_rtx_REG (HImode
, 0);
1160 emit_insn (gen_pop (ax
));
1163 emit_move_insn (dest
, ax
);
1164 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1165 emit_insn (gen_use (dest
));
1170 int need_bank
= i
/ 4;
1172 if (need_bank
!= rb
)
1174 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1177 emit_insn (gen_pop (dest
));
1182 emit_insn (gen_sel_rb (GEN_INT (0)));
1184 if (cfun
->machine
->trampolines_used
)
1185 emit_insn (gen_trampoline_uninit ());
1187 if (is_brk_interrupt_func (cfun
->decl
))
1188 emit_jump_insn (gen_brk_interrupt_return ());
1189 else if (is_interrupt_func (cfun
->decl
))
1190 emit_jump_insn (gen_interrupt_return ());
1192 emit_jump_insn (gen_rl78_return ());
1195 /* Likewise, for exception handlers. */
1197 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1199 /* FIXME - replace this with an indirect jump with stack adjust. */
1200 emit_jump_insn (gen_rl78_return ());
1203 #undef TARGET_ASM_FUNCTION_PROLOGUE
1204 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1206 /* We don't use this to actually emit the function prologue. We use
1207 this to insert a comment in the asm file describing the
1210 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1214 if (cfun
->machine
->framesize
== 0)
1216 fprintf (file
, "\t; start of function\n");
1218 if (cfun
->machine
->framesize_regs
)
1220 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1221 for (i
= 0; i
< 16; i
++)
1222 if (cfun
->machine
->need_to_push
[i
])
1223 fprintf (file
, " %s", word_regnames
[i
*2]);
1224 fprintf (file
, "\n");
1227 if (frame_pointer_needed
)
1228 fprintf (file
, "\t; $fp points here (r22)\n");
1230 if (cfun
->machine
->framesize_locals
)
1231 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1232 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1234 if (cfun
->machine
->framesize_outgoing
)
1235 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1236 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1239 /* Return an RTL describing where a function return value of type RET_TYPE
1242 #undef TARGET_FUNCTION_VALUE
1243 #define TARGET_FUNCTION_VALUE rl78_function_value
1246 rl78_function_value (const_tree ret_type
,
1247 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1248 bool outgoing ATTRIBUTE_UNUSED
)
1250 machine_mode mode
= TYPE_MODE (ret_type
);
1252 return gen_rtx_REG (mode
, 8);
1255 #undef TARGET_PROMOTE_FUNCTION_MODE
1256 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1259 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1261 int *punsignedp ATTRIBUTE_UNUSED
,
1262 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1267 /* Return an RTL expression describing the register holding a function
1268 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1269 be passed on the stack. CUM describes the previous parameters to the
1270 function and NAMED is false if the parameter is part of a variable
1271 parameter list, or the last named parameter before the start of a
1272 variable parameter list. */
1274 #undef TARGET_FUNCTION_ARG
1275 #define TARGET_FUNCTION_ARG rl78_function_arg
1278 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1279 machine_mode mode ATTRIBUTE_UNUSED
,
1280 const_tree type ATTRIBUTE_UNUSED
,
1281 bool named ATTRIBUTE_UNUSED
)
1286 #undef TARGET_FUNCTION_ARG_ADVANCE
1287 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1290 rl78_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
, const_tree type
,
1291 bool named ATTRIBUTE_UNUSED
)
1294 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1296 rounded_size
= ((mode
== BLKmode
)
1297 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1298 if (rounded_size
& 1)
1300 (*cum
) += rounded_size
;
1303 #undef TARGET_FUNCTION_ARG_BOUNDARY
1304 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1307 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED
,
1308 const_tree type ATTRIBUTE_UNUSED
)
1313 /* Supported modifier letters:
1315 A - address of a MEM
1316 S - SADDR form of a real register
1317 v - real register corresponding to a virtual register
1318 m - minus - negative of CONST_INT value.
1319 C - inverse of a conditional (NE vs EQ for example)
1320 C - complement of an integer
1321 z - collapsed conditional
1322 s - shift count mod 8
1323 S - shift count mod 16
1324 r - reverse shift count (8-(count mod 8))
1327 h - bottom HI of an SI
1329 q - bottom QI of an HI
1331 e - third QI of an SI (i.e. where the ES register gets values from)
1332 E - fourth QI of an SI (i.e. MSB)
1336 /* Implements the bulk of rl78_print_operand, below. We do it this
1337 way because we need to test for a constant at the top level and
1338 insert the '#', but not test for it anywhere else as we recurse
1339 down into the operand. */
1341 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1345 switch (GET_CODE (op
))
1349 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1352 if (rl78_far_p (op
))
1354 fprintf (file
, "es:");
1355 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1359 op
= adjust_address (op
, HImode
, 2);
1364 op
= adjust_address (op
, HImode
, 0);
1369 op
= adjust_address (op
, QImode
, 1);
1374 op
= adjust_address (op
, QImode
, 0);
1379 op
= adjust_address (op
, QImode
, 2);
1384 op
= adjust_address (op
, QImode
, 3);
1387 if (CONSTANT_P (XEXP (op
, 0)))
1389 fprintf (file
, "!");
1390 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1392 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1393 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1395 fprintf (file
, "!");
1396 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1398 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1399 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1400 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1402 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1403 fprintf (file
, "[");
1404 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1405 fprintf (file
, "]");
1409 fprintf (file
, "[");
1410 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1411 fprintf (file
, "]");
1418 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1419 else if (letter
== 'H')
1420 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1421 else if (letter
== 'q')
1422 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1423 else if (letter
== 'e')
1424 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1425 else if (letter
== 'E')
1426 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1427 else if (letter
== 'S')
1428 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1429 else if (GET_MODE (op
) == HImode
1430 && ! (REGNO (op
) & ~0xfe))
1433 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1435 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1438 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1443 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1444 else if (letter
== 'H')
1445 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1446 else if (letter
== 'q')
1447 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1448 else if (letter
== 'h')
1449 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1450 else if (letter
== 'e')
1451 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1452 else if (letter
== 'B')
1453 fprintf (file
, "%d", exact_log2 (INTVAL (op
)));
1454 else if (letter
== 'E')
1455 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1456 else if (letter
== 'm')
1457 fprintf (file
, "%ld", - INTVAL (op
));
1458 else if (letter
== 's')
1459 fprintf (file
, "%ld", INTVAL (op
) % 8);
1460 else if (letter
== 'S')
1461 fprintf (file
, "%ld", INTVAL (op
) % 16);
1462 else if (letter
== 'r')
1463 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1464 else if (letter
== 'C')
1465 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1467 fprintf (file
, "%ld", INTVAL (op
));
1471 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1476 int bits
= INTVAL (XEXP (op
, 1));
1477 int ofs
= INTVAL (XEXP (op
, 2));
1478 if (bits
== 16 && ofs
== 0)
1479 fprintf (file
, "%%lo16(");
1480 else if (bits
== 16 && ofs
== 16)
1481 fprintf (file
, "%%hi16(");
1482 else if (bits
== 8 && ofs
== 16)
1483 fprintf (file
, "%%hi8(");
1486 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1487 fprintf (file
, ")");
1492 if (GET_CODE (XEXP (op
, 0)) == REG
)
1493 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1495 print_rtl (file
, op
);
1502 fprintf (file
, "%%hi16(");
1508 fprintf (file
, "%%lo16(");
1514 fprintf (file
, "%%hi8(");
1518 if (letter
== 'q' || letter
== 'Q')
1519 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1521 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1523 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1524 fprintf (file
, "+");
1525 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1529 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1530 fprintf (file
, "+");
1531 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1534 fprintf (file
, ")");
1541 fprintf (file
, "%%hi16(");
1547 fprintf (file
, "%%lo16(");
1553 fprintf (file
, "%%hi8(");
1557 if (letter
== 'q' || letter
== 'Q')
1558 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1560 output_addr_const (file
, op
);
1562 fprintf (file
, ")");
1567 output_asm_label (op
);
1572 fprintf (file
, "#comparison eliminated");
1574 fprintf (file
, letter
== 'C' ? "nc" : "c");
1578 fprintf (file
, "br");
1580 fprintf (file
, letter
== 'C' ? "h" : "nh");
1584 fprintf (file
, "br");
1586 fprintf (file
, letter
== 'C' ? "c" : "nc");
1590 fprintf (file
, "#comparison eliminated");
1592 fprintf (file
, letter
== 'C' ? "nh" : "h");
1596 fprintf (file
, "br");
1598 fprintf (file
, letter
== 'C' ? "nz" : "z");
1602 fprintf (file
, "#comparison eliminated");
1604 fprintf (file
, letter
== 'C' ? "z" : "nz");
1607 /* Note: these assume appropriate adjustments were made so that
1608 unsigned comparisons, which is all this chip has, will
1612 fprintf (file
, "#comparison eliminated");
1614 fprintf (file
, letter
== 'C' ? "nc" : "c");
1618 fprintf (file
, "br");
1620 fprintf (file
, letter
== 'C' ? "h" : "nh");
1624 fprintf (file
, "br");
1626 fprintf (file
, letter
== 'C' ? "c" : "nc");
1630 fprintf (file
, "#comparison eliminated");
1632 fprintf (file
, letter
== 'C' ? "nh" : "h");
1636 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1641 #undef TARGET_PRINT_OPERAND
1642 #define TARGET_PRINT_OPERAND rl78_print_operand
1645 rl78_print_operand (FILE * file
, rtx op
, int letter
)
1647 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
1648 fprintf (file
, "#");
1649 rl78_print_operand_1 (file
, op
, letter
);
1652 #undef TARGET_TRAMPOLINE_INIT
1653 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1655 /* Note that the RL78's addressing makes it very difficult to do
1656 trampolines on the stack. So, libgcc has a small pool of
1657 trampolines from which one is allocated to this task. */
1659 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
1661 rtx mov_addr
, thunk_addr
;
1662 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
1664 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
1665 thunk_addr
= gen_reg_rtx (HImode
);
1667 function
= force_reg (HImode
, function
);
1668 static_chain
= force_reg (HImode
, static_chain
);
1670 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
1671 emit_move_insn (mov_addr
, thunk_addr
);
1673 cfun
->machine
->trampolines_used
= 1;
1676 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1677 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1680 rl78_trampoline_adjust_address (rtx m_tramp
)
1682 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
1686 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1687 the "normal" compares, specifically, it only has unsigned compares,
1688 so we must synthesize the missing ones. */
1690 rl78_expand_compare (rtx
*operands
)
1692 if (GET_CODE (operands
[2]) == MEM
)
1693 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
1698 /* Define this to 1 if you are debugging the peephole optimizers. */
1699 #define DEBUG_PEEP 0
1701 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1702 The default "word" size is a byte so we can effectively use all the
1703 registers, but we want to do 16-bit moves whenever possible. This
1704 function determines when such a move is an option. */
1706 rl78_peep_movhi_p (rtx
*operands
)
1711 /* (set (op0) (op1))
1712 (set (op2) (op3)) */
1714 if (! rl78_virt_insns_ok ())
1718 fprintf (stderr
, "\033[33m");
1719 debug_rtx (operands
[0]);
1720 debug_rtx (operands
[1]);
1721 debug_rtx (operands
[2]);
1722 debug_rtx (operands
[3]);
1723 fprintf (stderr
, "\033[0m");
1726 /* You can move a constant to memory as QImode, but not HImode. */
1727 if (GET_CODE (operands
[0]) == MEM
1728 && GET_CODE (operands
[1]) != REG
)
1731 fprintf (stderr
, "no peep: move constant to memory\n");
1736 if (rtx_equal_p (operands
[0], operands
[3]))
1739 fprintf (stderr
, "no peep: overlapping\n");
1744 for (i
= 0; i
< 2; i
++)
1746 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
1749 fprintf (stderr
, "no peep: different codes\n");
1753 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
1756 fprintf (stderr
, "no peep: different modes\n");
1761 switch (GET_CODE (operands
[i
]))
1765 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
1766 || GET_MODE (operands
[i
]) != QImode
)
1769 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
1770 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
1775 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
1778 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
1788 if (GET_MODE (operands
[i
]) != QImode
)
1790 if (MEM_ALIGN (operands
[i
]) < 16)
1792 a
= XEXP (operands
[i
], 0);
1793 if (GET_CODE (a
) == CONST
)
1795 if (GET_CODE (a
) == PLUS
)
1797 if (GET_CODE (a
) == CONST_INT
1801 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
1802 debug_rtx (operands
[i
]);
1806 m
= adjust_address (operands
[i
], QImode
, 1);
1807 if (! rtx_equal_p (m
, operands
[i
+2]))
1810 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
1812 debug_rtx (operands
[i
+2]);
1820 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
1826 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
1831 /* Likewise, when a peephole is activated, this function helps compute
1832 the new operands. */
1834 rl78_setup_peep_movhi (rtx
*operands
)
1838 for (i
= 0; i
< 2; i
++)
1840 switch (GET_CODE (operands
[i
]))
1843 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
1847 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char) INTVAL (operands
[i
+2])) * 256);
1851 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
1861 How Devirtualization works in the RL78 GCC port
1865 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1866 bytes of register space, in four banks, memory-mapped. One bank is
1867 the "selected" bank and holds the registers used for primary
1868 operations. Since the registers are memory mapped, often you can
1869 still refer to the unselected banks via memory accesses.
1873 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1874 and refers to the other banks via their memory addresses, although
1875 they're treated as regular registers internally. These "virtual"
1876 registers are R8 through R23 (bank3 is reserved for asm-based
1877 interrupt handlers).
1879 There are four machine description files:
1881 rl78.md - common register-independent patterns and definitions
1882 rl78-expand.md - expanders
1883 rl78-virt.md - patterns that match BEFORE devirtualization
1884 rl78-real.md - patterns that match AFTER devirtualization
1886 At least through register allocation and reload, gcc is told that it
1887 can do pretty much anything - but may only use the virtual registers.
1888 GCC cannot properly create the varying addressing modes that the RL78
1889 supports in an efficient way.
1891 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1892 uses the "valloc" attribute in rl78-virt.md for determining the rules
1893 by which it will replace virtual registers with real registers (or
1894 not) and how to make up addressing modes. For example, insns tagged
1895 with "ro1" have a single read-only parameter, which may need to be
1896 moved from memory/constant/vreg to a suitable real register. As part
1897 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1898 patterns and enabling the rl78-real.md patterns. The new patterns'
1899 constraints are used to determine the real registers used. NOTE:
1900 patterns in rl78-virt.md essentially ignore the constrains and rely on
1901 predicates, where the rl78-real.md ones essentially ignore the
1902 predicates and rely on the constraints.
1904 The devirtualization pass is scheduled via the pass manager (despite
1905 being called "rl78_reorg") so it can be scheduled prior to var-track
1906 (the idea is to let gdb know about the new registers). Ideally, it
1907 would be scheduled right after pro/epilogue generation, so the
1908 post-reload optimizers could operate on the real registers, but when I
1909 tried that there were some issues building the target libraries.
1911 During devirtualization, a simple register move optimizer is run. It
1912 would be better to run a full CSE/propogation pass on it though, but
1913 that has not yet been attempted.
1916 #define DEBUG_ALLOC 0
1918 #define OP(x) (*recog_data.operand_loc[x])
1920 /* This array is used to hold knowledge about the contents of the
1921 real registers (A ... H), the memory-based registers (r8 ... r31)
1922 and the first NUM_STACK_LOCS words on the stack. We use this to
1923 avoid generating redundant move instructions.
1925 A value in the range 0 .. 31 indicates register A .. r31.
1926 A value in the range 32 .. 63 indicates stack slot (value - 32).
1927 A value of NOT_KNOWN indicates that the contents of that location
1930 #define NUM_STACK_LOCS 32
1931 #define NOT_KNOWN 127
1933 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
1935 static unsigned char saved_update_index
= NOT_KNOWN
;
1936 static unsigned char saved_update_value
;
1937 static machine_mode saved_update_mode
;
1941 clear_content_memory (void)
1943 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
1945 fprintf (dump_file
, " clear content memory\n");
1946 saved_update_index
= NOT_KNOWN
;
1949 /* Convert LOC into an index into the content_memory array.
1950 If LOC cannot be converted, return NOT_KNOWN. */
1952 static unsigned char
1953 get_content_index (rtx loc
)
1957 if (loc
== NULL_RTX
)
1962 if (REGNO (loc
) < 32)
1967 mode
= GET_MODE (loc
);
1969 if (! rl78_stack_based_mem (loc
, mode
))
1972 loc
= XEXP (loc
, 0);
1975 /* loc = MEM (SP) */
1978 /* loc = MEM (PLUS (SP, INT)). */
1979 loc
= XEXP (loc
, 1);
1981 if (INTVAL (loc
) < NUM_STACK_LOCS
)
1982 return 32 + INTVAL (loc
);
1987 /* Return a string describing content INDEX in mode MODE.
1988 WARNING: Can return a pointer to a static buffer. */
1990 get_content_name (unsigned char index
, machine_mode mode
)
1992 static char buffer
[128];
1994 if (index
== NOT_KNOWN
)
1998 sprintf (buffer
, "stack slot %d", index
- 32);
1999 else if (mode
== HImode
)
2000 sprintf (buffer
, "%s%s",
2001 reg_names
[index
+ 1], reg_names
[index
]);
2003 return reg_names
[index
];
2011 display_content_memory (FILE * file
)
2015 fprintf (file
, " Known memory contents:\n");
2017 for (i
= 0; i
< sizeof content_memory
; i
++)
2018 if (content_memory
[i
] != NOT_KNOWN
)
2020 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
2021 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2027 update_content (unsigned char index
, unsigned char val
, machine_mode mode
)
2031 gcc_assert (index
< sizeof content_memory
);
2033 content_memory
[index
] = val
;
2034 if (val
!= NOT_KNOWN
)
2035 content_memory
[val
] = index
;
2037 /* Make the entry in dump_file *before* VAL is increased below. */
2040 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2041 if (val
== NOT_KNOWN
)
2042 fprintf (dump_file
, "Unknown\n");
2044 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2049 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2051 content_memory
[index
+ 1] = val
;
2052 if (val
!= NOT_KNOWN
)
2054 content_memory
[val
] = index
+ 1;
2059 /* Any other places that had INDEX recorded as their contents are now invalid. */
2060 for (i
= 0; i
< sizeof content_memory
; i
++)
2063 || (val
!= NOT_KNOWN
&& i
== val
))
2070 if (content_memory
[i
] == index
2071 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2073 content_memory
[i
] = NOT_KNOWN
;
2076 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2079 content_memory
[++ i
] = NOT_KNOWN
;
2084 /* Record that LOC contains VALUE.
2085 For HImode locations record that LOC+1 contains VALUE+1.
2086 If LOC is not a register or stack slot, do nothing.
2087 If VALUE is not a register or stack slot, clear the recorded content. */
2090 record_content (rtx loc
, rtx value
)
2093 unsigned char index
;
2096 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2099 val
= get_content_index (value
);
2101 mode
= GET_MODE (loc
);
2108 /* This should not happen when optimizing. */
2110 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2111 get_content_name (val
, mode
));
2118 update_content (index
, val
, mode
);
2121 /* Returns TRUE if LOC already contains a copy of VALUE. */
2124 already_contains (rtx loc
, rtx value
)
2126 unsigned char index
;
2129 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2132 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2135 if (content_memory
[index
] != val
)
2138 if (GET_MODE (loc
) == HImode
)
2139 return content_memory
[index
+ 1] == val
+ 1;
2145 rl78_es_addr (rtx addr
)
2147 if (GET_CODE (addr
) == MEM
)
2148 addr
= XEXP (addr
, 0);
2149 if (GET_CODE (addr
) != UNSPEC
)
2151 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2157 rl78_es_base (rtx addr
)
2159 if (GET_CODE (addr
) == MEM
)
2160 addr
= XEXP (addr
, 0);
2161 addr
= XVECEXP (addr
, 0, 1);
2162 if (GET_CODE (addr
) == CONST
2163 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2164 addr
= XEXP (XEXP (addr
, 0), 0);
2165 /* Mode doesn't matter here. */
2166 return gen_rtx_MEM (HImode
, addr
);
2169 /* Rescans an insn to see if it's recognized again. This is done
2170 carefully to ensure that all the constraint information is accurate
2171 for the newly matched insn. */
2173 insn_ok_now (rtx_insn
*insn
)
2175 rtx pattern
= PATTERN (insn
);
2178 INSN_CODE (insn
) = -1;
2180 if (recog (pattern
, insn
, 0) > -1)
2182 extract_insn (insn
);
2183 if (constrain_operands (1, get_preferred_alternatives (insn
)))
2186 fprintf (stderr
, "\033[32m");
2188 fprintf (stderr
, "\033[0m");
2190 if (SET_P (pattern
))
2191 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2193 /* We need to detect far addresses that haven't been
2194 converted to es/lo16 format. */
2195 for (i
=0; i
<recog_data
.n_operands
; i
++)
2196 if (GET_CODE (OP (i
)) == MEM
2197 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2198 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2206 /* We need to re-recog the insn with virtual registers to get
2208 cfun
->machine
->virt_insns_ok
= 1;
2209 if (recog (pattern
, insn
, 0) > -1)
2211 extract_insn (insn
);
2212 if (constrain_operands (0, get_preferred_alternatives (insn
)))
2214 cfun
->machine
->virt_insns_ok
= 0;
2220 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2227 fprintf (stderr
, "\033[31m");
2229 fprintf (stderr
, "\033[0m");
2235 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2236 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2237 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2238 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2239 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2241 #define FAILED gcc_unreachable ()
2242 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2243 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2246 /* Registers into which we move the contents of virtual registers. */
2247 #define X gen_rtx_REG (QImode, X_REG)
2248 #define A gen_rtx_REG (QImode, A_REG)
2249 #define C gen_rtx_REG (QImode, C_REG)
2250 #define B gen_rtx_REG (QImode, B_REG)
2251 #define E gen_rtx_REG (QImode, E_REG)
2252 #define D gen_rtx_REG (QImode, D_REG)
2253 #define L gen_rtx_REG (QImode, L_REG)
2254 #define H gen_rtx_REG (QImode, H_REG)
2256 #define AX gen_rtx_REG (HImode, AX_REG)
2257 #define BC gen_rtx_REG (HImode, BC_REG)
2258 #define DE gen_rtx_REG (HImode, DE_REG)
2259 #define HL gen_rtx_REG (HImode, HL_REG)
2261 /* Returns TRUE if R is a virtual register. */
2263 is_virtual_register (rtx r
)
2265 return (GET_CODE (r
) == REG
2270 /* In all these alloc routines, we expect the following: the insn
2271 pattern is unshared, the insn was previously recognized and failed
2272 due to predicates or constraints, and the operand data is in
2275 static int virt_insn_was_frame
;
2277 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2280 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2283 fprintf (stderr
, "\033[36m%d: ", line
);
2285 fprintf (stderr
, "\033[0m");
2287 /*SCHED_GROUP_P (r) = 1;*/
2288 if (virt_insn_was_frame
)
2289 RTX_FRAME_RELATED_P (r
) = 1;
2293 #define EM(x) EM2 (__LINE__, x)
2295 /* Return a suitable RTX for the low half of a __far address. */
2297 rl78_lo16 (rtx addr
)
2301 if (GET_CODE (addr
) == SYMBOL_REF
2302 || GET_CODE (addr
) == CONST
)
2304 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2305 r
= gen_rtx_CONST (HImode
, r
);
2308 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2310 r
= gen_es_addr (r
);
2315 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2319 if (GET_CODE (addr
) == SYMBOL_REF
2320 || GET_CODE (addr
) == CONST
)
2322 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2323 r
= gen_rtx_CONST (QImode
, r
);
2326 return rl78_subreg (QImode
, addr
, SImode
, 2);
2330 add_postponed_content_update (rtx to
, rtx value
)
2332 unsigned char index
;
2334 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2337 gcc_assert (saved_update_index
== NOT_KNOWN
);
2338 saved_update_index
= index
;
2339 saved_update_value
= get_content_index (value
);
2340 saved_update_mode
= GET_MODE (to
);
2344 process_postponed_content_update (void)
2346 if (saved_update_index
!= NOT_KNOWN
)
2348 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2349 saved_update_index
= NOT_KNOWN
;
2353 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2354 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2355 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2356 BEFORE is true, FROM otherwise. */
2358 gen_and_emit_move (rtx to
, rtx from
, rtx where
, bool before
)
2360 machine_mode mode
= GET_MODE (to
);
2362 if (optimize
&& before
&& already_contains (to
, from
))
2365 display_content_memory (stderr
);
2369 fprintf (dump_file
, " Omit move of %s into ",
2370 get_content_name (get_content_index (from
), mode
));
2371 fprintf (dump_file
, "%s as it already contains this value\n",
2372 get_content_name (get_content_index (to
), mode
));
2377 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2381 if (where
== NULL_RTX
)
2384 emit_insn_before (move
, where
);
2387 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2389 /* If necessary move REG_EH_REGION notes forward.
2390 cf. compiling gcc.dg/pr44545.c. */
2391 if (note
!= NULL_RTX
)
2393 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2394 remove_note (where
, note
);
2397 emit_insn_after (move
, where
);
2401 record_content (to
, from
);
2403 add_postponed_content_update (to
, from
);
2406 return before
? to
: from
;
2409 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2410 copy it into NEWBASE and return the updated MEM. Otherwise just
2411 return M. Any needed insns are emitted before BEFORE. */
2413 transcode_memory_rtx (rtx m
, rtx newbase
, rtx before
)
2415 rtx base
, index
, addendr
;
2422 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2425 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2428 fprintf (stderr
, "setting ES:\n");
2431 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2432 emit_insn_before (EM (gen_movqi_es (A
)), before
);
2433 record_content (A
, NULL_RTX
);
2435 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2436 MEM_COPY_ATTRIBUTES (new_m
, m
);
2441 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2442 gcc_assert (index
== NULL_RTX
);
2445 fprintf (stderr
, "\033[33m"); debug_rtx (m
); fprintf (stderr
, "\033[0m");
2448 if (base
== NULL_RTX
)
2451 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2452 addend
= INTVAL (addendr
);
2454 gcc_assert (REG_P (base
));
2455 gcc_assert (REG_P (newbase
));
2457 if (REGNO (base
) == SP_REG
)
2459 if (addend
>= 0 && addend
<= 255)
2463 /* BASE should be a virtual register. We copy it to NEWBASE. If
2464 the addend is out of range for DE/HL, we use AX to compute the full
2468 || (addend
> 255 && REGNO (newbase
) != 2)
2469 || (addendr
&& GET_CODE (addendr
) != CONST_INT
))
2474 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2475 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2476 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2477 record_content (AX
, NULL_RTX
);
2478 record_content (newbase
, NULL_RTX
);
2485 base
= gen_and_emit_move (newbase
, base
, before
, true);
2490 record_content (base
, NULL_RTX
);
2491 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2495 fprintf (stderr
, "\033[33m");
2499 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2501 m
= change_address (m
, GET_MODE (m
), base
);
2504 fprintf (stderr
, "\033[0m");
2509 /* Copy SRC to accumulator (A or AX), placing any generated insns
2510 before BEFORE. Returns accumulator RTX. */
2512 move_to_acc (int opno
, rtx before
)
2514 rtx src
= OP (opno
);
2515 machine_mode mode
= GET_MODE (src
);
2517 if (REG_P (src
) && REGNO (src
) < 2)
2520 if (mode
== VOIDmode
)
2521 mode
= recog_data
.operand_mode
[opno
];
2523 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2527 force_into_acc (rtx src
, rtx before
)
2529 machine_mode mode
= GET_MODE (src
);
2532 if (REG_P (src
) && REGNO (src
) < 2)
2535 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2539 emit_insn_before (move
, before
);
2540 record_content (AX
, NULL_RTX
);
2543 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2544 after AFTER. Returns accumulator RTX. */
2546 move_from_acc (unsigned int opno
, rtx after
)
2548 rtx dest
= OP (opno
);
2549 machine_mode mode
= GET_MODE (dest
);
2551 if (REG_P (dest
) && REGNO (dest
) < 2)
2554 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2557 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2558 before BEFORE. Returns reg RTX. */
2560 move_acc_to_reg (rtx acc
, int regno
, rtx before
)
2562 machine_mode mode
= GET_MODE (acc
);
2565 reg
= gen_rtx_REG (mode
, regno
);
2567 return gen_and_emit_move (reg
, acc
, before
, true);
2570 /* Copy SRC to X, placing any generated insns before BEFORE.
2573 move_to_x (int opno
, rtx before
)
2575 rtx src
= OP (opno
);
2576 machine_mode mode
= GET_MODE (src
);
2579 if (mode
== VOIDmode
)
2580 mode
= recog_data
.operand_mode
[opno
];
2581 reg
= (mode
== QImode
) ? X
: AX
;
2583 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2585 OP (opno
) = move_to_acc (opno
, before
);
2586 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
2590 return gen_and_emit_move (reg
, src
, before
, true);
2593 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2594 Returns H/HL RTX. */
2596 move_to_hl (int opno
, rtx before
)
2598 rtx src
= OP (opno
);
2599 machine_mode mode
= GET_MODE (src
);
2602 if (mode
== VOIDmode
)
2603 mode
= recog_data
.operand_mode
[opno
];
2604 reg
= (mode
== QImode
) ? L
: HL
;
2606 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2608 OP (opno
) = move_to_acc (opno
, before
);
2609 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
2613 return gen_and_emit_move (reg
, src
, before
, true);
2616 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2617 Returns E/DE RTX. */
2619 move_to_de (int opno
, rtx before
)
2621 rtx src
= OP (opno
);
2622 machine_mode mode
= GET_MODE (src
);
2625 if (mode
== VOIDmode
)
2626 mode
= recog_data
.operand_mode
[opno
];
2628 reg
= (mode
== QImode
) ? E
: DE
;
2630 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2632 OP (opno
) = move_to_acc (opno
, before
);
2633 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
2637 gen_and_emit_move (reg
, src
, before
, true);
2643 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2645 rl78_alloc_physical_registers_op1 (rtx_insn
*insn
)
2647 /* op[0] = func op[1] */
2649 /* We first try using A as the destination, then copying it
2651 if (rtx_equal_p (OP (0), OP (1)))
2654 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2658 /* If necessary, load the operands into BC and HL.
2659 Check to see if we already have OP (0) in HL
2660 and if so, swap the order. */
2662 && already_contains (HL
, XEXP (OP (0), 0)))
2664 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
2665 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
2669 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2670 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
2676 OP (0) = move_from_acc (0, insn
);
2680 /* Try copying the src to acc first, then. This is for, for
2681 example, ZERO_EXTEND or NOT. */
2682 OP (1) = move_to_acc (1, insn
);
2687 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2688 Assumes that the current insn has already been recognised and hence the
2689 constraint data has been filled in. */
2691 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
2693 const char * p
= recog_data
.constraints
[opnum
];
2695 /* No constraints means anything is accepted. */
2696 if (p
== NULL
|| *p
== 0 || *p
== ',')
2705 len
= CONSTRAINT_LEN (c
, p
);
2706 gcc_assert (len
> 0);
2714 if (lookup_constraint (p
) == constraint
)
2722 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2724 rl78_alloc_physical_registers_op2 (rtx_insn
*insn
)
2732 if (rtx_equal_p (OP (0), OP (1)))
2735 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2736 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2738 else if (rtx_equal_p (OP (0), OP (2)))
2740 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2742 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2746 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2747 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2748 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2753 prev
= prev_nonnote_nondebug_insn (insn
);
2754 if (recog_data
.constraints
[1][0] == '%'
2755 && is_virtual_register (OP (1))
2756 && ! is_virtual_register (OP (2))
2757 && ! CONSTANT_P (OP (2)))
2764 /* Make a note of whether (H)L is being used. It matters
2765 because if OP (2) also needs reloading, then we must take
2766 care not to corrupt HL. */
2767 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
2769 /* If HL is not currently being used and dest == op1 then there are
2770 some possible optimizations available by reloading one of the
2771 operands into HL, before trying to use the accumulator. */
2774 && rtx_equal_p (OP (0), OP (1)))
2776 /* If op0 is a Ws1 type memory address then switching the base
2777 address register to HL might allow us to perform an in-memory
2778 operation. (eg for the INCW instruction).
2780 FIXME: Adding the move into HL is costly if this optimization is not
2781 going to work, so for now, make sure that we know that the new insn will
2782 match the requirements of the addhi3_real pattern. Really we ought to
2783 generate a candidate sequence, test that, and then install it if the
2784 results are good. */
2785 if (satisfies_constraint_Ws1 (OP (0))
2786 && has_constraint (0, CONSTRAINT_Wh1
)
2787 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2789 rtx base
, index
, addend
, newbase
;
2791 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
2792 gcc_assert (index
== NULL_RTX
);
2793 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2795 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2796 if (addend
!= NULL_RTX
)
2798 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
2799 record_content (newbase
, NULL_RTX
);
2800 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
2802 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
2804 /* We do not want to fail here as this means that
2805 we have inserted useless insns into the stream. */
2809 else if (REG_P (OP (0))
2810 && satisfies_constraint_Ws1 (OP (2))
2811 && has_constraint (2, CONSTRAINT_Wh1
))
2813 rtx base
, index
, addend
, newbase
;
2815 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
2816 gcc_assert (index
== NULL_RTX
);
2817 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2819 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2820 if (addend
!= NULL_RTX
)
2822 gen_and_emit_move (HL
, base
, insn
, true);
2824 if (REGNO (OP (0)) != X_REG
)
2826 OP (1) = move_to_acc (1, insn
);
2827 OP (0) = move_from_acc (0, insn
);
2830 record_content (HL
, NULL_RTX
);
2831 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
2833 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
2835 /* We do not want to fail here as this means that
2836 we have inserted useless insns into the stream. */
2842 OP (0) = move_from_acc (0, insn
);
2844 tmp_id
= get_max_insn_count ();
2847 if (rtx_equal_p (OP (1), OP (2)))
2848 OP (2) = OP (1) = move_to_acc (1, insn
);
2850 OP (1) = move_to_acc (1, insn
);
2854 /* If we omitted the move of OP1 into the accumulator (because
2855 it was already there from a previous insn), then force the
2856 generation of the move instruction now. We know that we
2857 are about to emit a move into HL (or DE) via AX, and hence
2858 our optimization to remove the load of OP1 is no longer valid. */
2859 if (tmp_id
== get_max_insn_count ())
2860 force_into_acc (saved_op1
, insn
);
2862 /* We have to copy op2 to HL (or DE), but that involves AX, which
2863 already has a live value. Emit it before those insns. */
2866 first
= next_nonnote_nondebug_insn (prev
);
2868 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2871 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
2876 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2878 rl78_alloc_physical_registers_ro1 (rtx_insn
*insn
)
2880 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2884 OP (0) = move_to_acc (0, insn
);
2889 /* Devirtualize a compare insn. */
2891 rl78_alloc_physical_registers_cmp (rtx_insn
*insn
)
2895 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2898 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2899 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2901 /* HI compares have to have OP (1) in AX, but QI
2902 compares do not, so it is worth checking here. */
2905 /* For an HImode compare, OP (1) must always be in AX.
2906 But if OP (1) is a REG (and not AX), then we can avoid
2907 a reload of OP (1) if we reload OP (2) into AX and invert
2910 && REGNO (OP (1)) != AX_REG
2911 && GET_MODE (OP (1)) == HImode
2914 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
2916 OP (2) = move_to_acc (2, insn
);
2918 switch (GET_CODE (cmp
))
2923 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
2924 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
2925 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
2926 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
2939 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
2940 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
2942 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
2947 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2948 should be handled by the second alternative of the cbranchhi_real pattern. */
2949 if (rtx_equal_p (OP (1), OP (2)))
2951 OP (1) = OP (2) = BC
;
2955 tmp_id
= get_max_insn_count ();
2958 OP (1) = move_to_acc (1, insn
);
2962 /* If we omitted the move of OP1 into the accumulator (because
2963 it was already there from a previous insn), then force the
2964 generation of the move instruction now. We know that we
2965 are about to emit a move into HL via AX, and hence our
2966 optimization to remove the load of OP1 is no longer valid. */
2967 if (tmp_id
== get_max_insn_count ())
2968 force_into_acc (saved_op1
, insn
);
2970 /* We have to copy op2 to HL, but that involves the acc, which
2971 already has a live value. Emit it before those insns. */
2973 first
= next_nonnote_nondebug_insn (prev
);
2975 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2977 OP (2) = move_to_hl (2, first
);
2982 /* Like op2, but AX = A * X. */
2984 rl78_alloc_physical_registers_umul (rtx_insn
*insn
)
2986 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2991 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2992 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2993 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2997 if (recog_data
.constraints
[1][0] == '%'
2998 && is_virtual_register (OP (1))
2999 && !is_virtual_register (OP (2))
3000 && !CONSTANT_P (OP (2)))
3007 OP (0) = move_from_acc (0, insn
);
3009 tmp_id
= get_max_insn_count ();
3012 if (rtx_equal_p (OP (1), OP (2)))
3014 gcc_assert (GET_MODE (OP (2)) == QImode
);
3015 /* The MULU instruction does not support duplicate arguments
3016 but we know that if we copy OP (2) to X it will do so via
3017 A and thus OP (1) will already be loaded into A. */
3018 OP (2) = move_to_x (2, insn
);
3022 OP (1) = move_to_acc (1, insn
);
3026 /* If we omitted the move of OP1 into the accumulator (because
3027 it was already there from a previous insn), then force the
3028 generation of the move instruction now. We know that we
3029 are about to emit a move into HL (or DE) via AX, and hence
3030 our optimization to remove the load of OP1 is no longer valid. */
3031 if (tmp_id
== get_max_insn_count ())
3032 force_into_acc (saved_op1
, insn
);
3034 /* We have to copy op2 to X, but that involves the acc, which
3035 already has a live value. Emit it before those insns. */
3038 first
= next_nonnote_nondebug_insn (prev
);
3040 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3042 OP (2) = move_to_x (2, first
);
3048 rl78_alloc_address_registers_macax (rtx_insn
*insn
)
3051 bool replace_in_op0
= false;
3052 bool replace_in_op1
= false;
3056 /* Two different MEMs are not allowed. */
3058 for (op
= 2; op
>= 0; op
--)
3060 if (MEM_P (OP (op
)))
3062 if (op
== 0 && replace_in_op0
)
3064 if (op
== 1 && replace_in_op1
)
3070 /* If we replace a MEM, make sure that we replace it for all
3071 occurrences of the same MEM in the insn. */
3072 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3073 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3075 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3078 && ((GET_CODE (XEXP (OP (op
), 0)) == REG
3079 && REGNO (XEXP (OP (op
), 0)) == SP_REG
)
3080 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3081 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3083 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3084 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3092 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3095 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3105 /* Scan all insns and devirtualize them. */
3107 rl78_alloc_physical_registers (void)
3109 /* During most of the compile, gcc is dealing with virtual
3110 registers. At this point, we need to assign physical registers
3111 to the vitual ones, and copy in/out as needed. */
3113 rtx_insn
*insn
, *curr
;
3114 enum attr_valloc valloc_method
;
3116 for (insn
= get_insns (); insn
; insn
= curr
)
3120 curr
= next_nonnote_nondebug_insn (insn
);
3123 && (GET_CODE (PATTERN (insn
)) == SET
3124 || GET_CODE (PATTERN (insn
)) == CALL
)
3125 && INSN_CODE (insn
) == -1)
3127 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3129 i
= recog (PATTERN (insn
), insn
, 0);
3135 INSN_CODE (insn
) = i
;
3139 cfun
->machine
->virt_insns_ok
= 0;
3140 cfun
->machine
->real_insns_ok
= 1;
3142 clear_content_memory ();
3144 for (insn
= get_insns (); insn
; insn
= curr
)
3148 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3153 clear_content_memory ();
3159 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3161 pattern
= PATTERN (insn
);
3162 if (GET_CODE (pattern
) == PARALLEL
)
3163 pattern
= XVECEXP (pattern
, 0, 0);
3164 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3165 clear_content_memory ();
3166 if (GET_CODE (pattern
) != SET
3167 && GET_CODE (pattern
) != CALL
)
3169 if (GET_CODE (pattern
) == SET
3170 && GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3173 valloc_method
= get_attr_valloc (insn
);
3175 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3177 if (valloc_method
== VALLOC_MACAX
)
3179 record_content (AX
, NULL_RTX
);
3180 record_content (BC
, NULL_RTX
);
3181 record_content (DE
, NULL_RTX
);
3184 if (insn_ok_now (insn
))
3187 INSN_CODE (insn
) = -1;
3189 if (RTX_FRAME_RELATED_P (insn
))
3190 virt_insn_was_frame
= 1;
3192 virt_insn_was_frame
= 0;
3194 switch (valloc_method
)
3197 rl78_alloc_physical_registers_op1 (insn
);
3200 rl78_alloc_physical_registers_op2 (insn
);
3203 rl78_alloc_physical_registers_ro1 (insn
);
3206 rl78_alloc_physical_registers_cmp (insn
);
3209 rl78_alloc_physical_registers_umul (insn
);
3212 /* Macro that clobbers AX. */
3213 rl78_alloc_address_registers_macax (insn
);
3214 record_content (AX
, NULL_RTX
);
3215 record_content (BC
, NULL_RTX
);
3216 record_content (DE
, NULL_RTX
);
3220 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3221 clear_content_memory ();
3223 process_postponed_content_update ();
3227 fprintf (stderr
, "\033[0m");
3231 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3232 This function scans for uses of registers; the last use (i.e. first
3233 encounter when scanning backwards) triggers a REG_DEAD note if the
3234 reg was previously in DEAD[]. */
3236 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3245 code
= GET_CODE (s
);
3249 /* Compare registers by number. */
3254 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3255 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3256 print_rtl_single (dump_file
, s
);
3259 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3260 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3264 /* These codes have no constituent expressions
3275 /* These are kept unique for a given value. */
3282 fmt
= GET_RTX_FORMAT (code
);
3284 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3289 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3290 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3292 else if (fmt
[i
] == 'e')
3293 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3297 /* Like the previous function, but scan for SETs instead. */
3299 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3303 if (GET_CODE (d
) != REG
)
3308 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3310 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3311 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3315 /* This is a rather crude register death pass. Death status is reset
3316 at every jump or call insn. */
3318 rl78_calculate_death_notes (void)
3320 char dead
[FIRST_PSEUDO_REGISTER
];
3324 memset (dead
, 0, sizeof (dead
));
3326 for (insn
= get_last_insn ();
3328 insn
= prev_nonnote_nondebug_insn (insn
))
3332 fprintf (dump_file
, "\n--------------------------------------------------");
3333 fprintf (dump_file
, "\nDead:");
3334 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3336 fprintf (dump_file
, " %s", reg_names
[i
]);
3337 fprintf (dump_file
, "\n");
3338 print_rtl_single (dump_file
, insn
);
3341 switch (GET_CODE (insn
))
3345 switch (GET_CODE (p
))
3350 rl78_note_reg_set (dead
, d
, insn
);
3351 rl78_note_reg_uses (dead
, s
, insn
);
3355 rl78_note_reg_uses (dead
, p
, insn
);
3364 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3366 memset (dead
, 1, sizeof (dead
));
3367 /* We expect a USE just prior to this, which will mark
3368 the actual return registers. The USE will have a
3369 death note, but we aren't going to be modifying it
3374 memset (dead
, 0, sizeof (dead
));
3381 print_rtl_single (dump_file
, insn
);
3385 /* Helper function to reset the origins in RP and the age in AGE for
3388 reset_origins (int *rp
, int *age
)
3391 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3398 /* The idea behind this optimization is to look for cases where we
3399 move data from A to B to C, and instead move from A to B, and A to
3400 C. If B is a virtual register or memory, this is a big win on its
3401 own. If B turns out to be unneeded after this, it's a bigger win.
3402 For each register, we try to determine where it's value originally
3403 came from, if it's propogated purely through moves (and not
3404 computes). The ORIGINS[] array has the regno for the "origin" of
3405 the value in the [regno] it's indexed by. */
3407 rl78_propogate_register_origins (void)
3409 int origins
[FIRST_PSEUDO_REGISTER
];
3410 int age
[FIRST_PSEUDO_REGISTER
];
3412 rtx_insn
*insn
, *ninsn
= NULL
;
3415 reset_origins (origins
, age
);
3417 for (insn
= get_insns (); insn
; insn
= ninsn
)
3419 ninsn
= next_nonnote_nondebug_insn (insn
);
3423 fprintf (dump_file
, "\n");
3424 fprintf (dump_file
, "Origins:");
3425 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3426 if (origins
[i
] != i
)
3427 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
3428 fprintf (dump_file
, "\n");
3429 print_rtl_single (dump_file
, insn
);
3432 switch (GET_CODE (insn
))
3438 reset_origins (origins
, age
);
3445 pat
= PATTERN (insn
);
3447 if (GET_CODE (pat
) == PARALLEL
)
3449 rtx clobber
= XVECEXP (pat
, 0, 1);
3450 pat
= XVECEXP (pat
, 0, 0);
3451 if (GET_CODE (clobber
) == CLOBBER
3452 && GET_CODE (XEXP (clobber
, 0)) == REG
)
3454 int cr
= REGNO (XEXP (clobber
, 0));
3455 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
3457 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
3458 for (i
= 0; i
< mb
; i
++)
3460 origins
[cr
+ i
] = cr
+ i
;
3468 if (GET_CODE (pat
) == SET
)
3470 rtx src
= SET_SRC (pat
);
3471 rtx dest
= SET_DEST (pat
);
3472 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3474 if (GET_CODE (dest
) == REG
)
3476 int dr
= REGNO (dest
);
3478 if (GET_CODE (src
) == REG
)
3480 int sr
= REGNO (src
);
3482 int best_age
, best_reg
;
3484 /* See if the copy is not needed. */
3485 for (i
= 0; i
< mb
; i
++)
3486 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3491 fprintf (dump_file
, "deleting because dest already has correct value\n");
3496 if (dr
< 8 || sr
>= 8)
3502 /* See if the copy can be made from another
3503 bank 0 register instead, instead of the
3504 virtual src register. */
3505 for (ar
= 0; ar
< 8; ar
+= mb
)
3508 for (i
= 0; i
< mb
; i
++)
3509 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3512 /* The chip has some reg-reg move limitations. */
3513 if (mb
== 1 && dr
> 3)
3518 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3520 best_age
= age
[sr
+ i
];
3528 /* FIXME: copy debug info too. */
3529 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3534 for (i
= 0; i
< mb
; i
++)
3536 origins
[dr
+ i
] = origins
[sr
+ i
];
3537 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3542 /* The destination is computed, its origin is itself. */
3544 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3545 dr
, mb
, mb
== 1 ? "" : "s");
3546 for (i
= 0; i
< mb
; i
++)
3548 origins
[dr
+ i
] = dr
+ i
;
3553 /* Any registers marked with that reg as an origin are reset. */
3554 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3555 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3562 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3563 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3566 fprintf (dump_file
, "Resetting origin of AX/BC for macro.\n");
3567 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3568 if (i
<= 3 || origins
[i
] <= 3)
3575 if (GET_CODE (src
) == ASHIFT
3576 || GET_CODE (src
) == ASHIFTRT
3577 || GET_CODE (src
) == LSHIFTRT
)
3579 rtx count
= XEXP (src
, 1);
3580 if (GET_CODE (count
) == REG
)
3582 /* Special case - our pattern clobbers the count register. */
3583 int r
= REGNO (count
);
3585 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
3586 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3587 if (i
== r
|| origins
[i
] == r
)
3595 else if (GET_CODE (pat
) == CLOBBER
3596 && GET_CODE (XEXP (pat
, 0)) == REG
)
3598 if (REG_P (XEXP (pat
, 0)))
3600 unsigned int reg
= REGNO (XEXP (pat
, 0));
3610 /* Remove any SETs where the destination is unneeded. */
3612 rl78_remove_unused_sets (void)
3614 rtx_insn
*insn
, *ninsn
= NULL
;
3617 for (insn
= get_insns (); insn
; insn
= ninsn
)
3619 ninsn
= next_nonnote_nondebug_insn (insn
);
3621 rtx set
= single_set (insn
);
3625 dest
= SET_DEST (set
);
3627 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
3630 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
3635 /* This is the top of the devritualization pass. */
3639 /* split2 only happens when optimizing, but we need all movSIs to be
3644 rl78_alloc_physical_registers ();
3648 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3649 print_rtl_with_bb (dump_file
, get_insns (), 0);
3652 rl78_propogate_register_origins ();
3653 rl78_calculate_death_notes ();
3657 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3658 print_rtl_with_bb (dump_file
, get_insns (), 0);
3659 fprintf (dump_file
, "\n======================================================================\n");
3662 rl78_remove_unused_sets ();
3664 /* The code after devirtualizing has changed so much that at this point
3665 we might as well just rescan everything. Note that
3666 df_rescan_all_insns is not going to help here because it does not
3667 touch the artificial uses and defs. */
3668 df_finish_pass (true);
3670 df_live_add_problem ();
3671 df_scan_alloc (NULL
);
3678 #undef TARGET_RETURN_IN_MEMORY
3679 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3682 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
3684 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
3685 return (size
== -1 || size
> 8);
3689 #undef TARGET_RTX_COSTS
3690 #define TARGET_RTX_COSTS rl78_rtx_costs
3692 static bool rl78_rtx_costs (rtx x
,
3694 int outer_code ATTRIBUTE_UNUSED
,
3695 int opno ATTRIBUTE_UNUSED
,
3697 bool speed ATTRIBUTE_UNUSED
)
3699 if (code
== IF_THEN_ELSE
)
3700 return COSTS_N_INSNS (10);
3701 if (GET_MODE (x
) == SImode
)
3707 *total
= COSTS_N_INSNS (14);
3708 else if (RL78_MUL_G13
)
3709 *total
= COSTS_N_INSNS (29);
3711 *total
= COSTS_N_INSNS (500);
3714 *total
= COSTS_N_INSNS (8);
3719 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3721 switch (INTVAL (XEXP (x
, 1)))
3723 case 0: *total
= COSTS_N_INSNS (0); break;
3724 case 1: *total
= COSTS_N_INSNS (6); break;
3725 case 2: case 3: case 4: case 5: case 6: case 7:
3726 *total
= COSTS_N_INSNS (10); break;
3727 case 8: *total
= COSTS_N_INSNS (6); break;
3728 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3729 *total
= COSTS_N_INSNS (10); break;
3730 case 16: *total
= COSTS_N_INSNS (3); break;
3731 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3732 *total
= COSTS_N_INSNS (4); break;
3733 case 24: *total
= COSTS_N_INSNS (4); break;
3734 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3735 *total
= COSTS_N_INSNS (5); break;
3739 *total
= COSTS_N_INSNS (10+4*16);
3747 #undef TARGET_UNWIND_WORD_MODE
3748 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3751 rl78_unwind_word_mode (void)
3757 struct gcc_target targetm
= TARGET_INITIALIZER
;
3759 #include "gt-rl78.h"