1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2013 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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"
51 #include "tree-pass.h"
53 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
54 #include "insn-flags.h" /* for gen_*(). */
56 static inline bool is_interrupt_func (const_tree decl
);
57 static inline bool is_brk_interrupt_func (const_tree decl
);
58 static void rl78_reorg (void);
61 /* Debugging statements are tagged with DEBUG0 only so that they can
62 be easily enabled individually, by replacing the '0' with '1' as
67 /* REGISTER_NAMES has the names for individual 8-bit registers, but
68 these have the names we need to use when referring to 16-bit
70 static const char * const word_regnames
[] =
72 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
74 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
75 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
76 "sp", "ap", "psw", "es", "cs"
79 struct GTY(()) machine_function
81 /* If set, the rest of the fields have been computed. */
83 /* Which register pairs need to be pushed in the prologue. */
84 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
86 /* These fields describe the frame layout... */
88 /* 4 bytes for saved PC */
92 int framesize_outgoing
;
96 /* If set, recog is allowed to match against the "real" patterns. */
98 /* If set, recog is allowed to match against the "virtual" patterns. */
100 /* Set if the current function needs to clean up any trampolines. */
101 int trampolines_used
;
104 /* This is our init_machine_status, as set in
105 rl78_option_override. */
106 static struct machine_function
*
107 rl78_init_machine_status (void)
109 struct machine_function
*m
;
111 m
= ggc_alloc_cleared_machine_function ();
112 m
->virt_insns_ok
= 1;
117 /* Returns whether to run the devirtualization pass. */
124 /* Runs the devirtualization pass. */
132 /* This pass converts virtual instructions using virtual registers, to
133 real instructions using real registers. Rather than run it as
134 reorg, we reschedule it before vartrack to help with debugging. */
137 const pass_data pass_data_rl78_devirt
=
141 OPTGROUP_NONE
, /* optinfo_flags */
143 true, /* has_execute */
144 TV_MACH_DEP
, /* tv_id */
145 0, /* properties_required */
146 0, /* properties_provided */
147 0, /* properties_destroyed */
148 0, /* todo_flags_start */
149 0, /* todo_flags_finish */
152 class pass_rl78_devirt
: public rtl_opt_pass
155 pass_rl78_devirt(gcc::context
*ctxt
)
156 : rtl_opt_pass(pass_data_rl78_devirt
, ctxt
)
160 /* opt_pass methods: */
161 bool gate () { return devirt_gate (); }
162 unsigned int execute () { return devirt_pass (); }
168 make_pass_rl78_devirt (gcc::context
*ctxt
)
170 return new pass_rl78_devirt (ctxt
);
174 move_elim_pass (void)
176 rtx insn
, ninsn
, prev
= NULL_RTX
;
178 for (insn
= get_insns (); insn
; insn
= ninsn
)
182 ninsn
= next_nonnote_nondebug_insn (insn
);
184 if ((set
= single_set (insn
)) == NULL_RTX
)
190 /* If we have two SET insns in a row (without anything
191 between them) and the source of the second one is the
192 destination of the first one, and vice versa, then we
193 can eliminate the second SET. */
195 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
196 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
200 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
211 print_rtl_with_bb (dump_file
, get_insns (), 0);
218 const pass_data pass_data_rl78_move_elim
=
221 "move_elim", /* name */
222 OPTGROUP_NONE
, /* optinfo_flags */
224 true, /* has_execute */
225 TV_MACH_DEP
, /* tv_id */
226 0, /* properties_required */
227 0, /* properties_provided */
228 0, /* properties_destroyed */
229 0, /* todo_flags_start */
230 0, /* todo_flags_finish */
233 class pass_rl78_move_elim
: public rtl_opt_pass
236 pass_rl78_move_elim(gcc::context
*ctxt
)
237 : rtl_opt_pass(pass_data_rl78_move_elim
, ctxt
)
241 /* opt_pass methods: */
242 bool gate () { return devirt_gate (); }
243 unsigned int execute () { return move_elim_pass (); }
249 make_pass_rl78_move_elim (gcc::context
*ctxt
)
251 return new pass_rl78_move_elim (ctxt
);
254 #undef TARGET_ASM_FILE_START
255 #define TARGET_ASM_FILE_START rl78_asm_file_start
258 rl78_asm_file_start (void)
264 /* The memory used is 0xffec8 to 0xffedf; real registers are in
265 0xffee0 to 0xffee7. */
266 for (i
= 8; i
< 32; i
++)
267 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
271 for (i
= 0; i
< 8; i
++)
273 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
274 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
275 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
279 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
280 static struct register_pass_info rl78_devirt_info
=
285 PASS_POS_INSERT_BEFORE
288 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
289 static struct register_pass_info rl78_move_elim_info
=
294 PASS_POS_INSERT_AFTER
297 register_pass (& rl78_devirt_info
);
298 register_pass (& rl78_move_elim_info
);
302 #undef TARGET_OPTION_OVERRIDE
303 #define TARGET_OPTION_OVERRIDE rl78_option_override
306 rl78_option_override (void)
308 flag_omit_frame_pointer
= 1;
309 flag_no_function_cse
= 1;
310 flag_split_wide_types
= 0;
312 init_machine_status
= rl78_init_machine_status
;
317 for (i
=24; i
<32; i
++)
322 /* Most registers are 8 bits. Some are 16 bits because, for example,
323 gcc doesn't like dealing with $FP as a register pair. This table
324 maps register numbers to size in bytes. */
325 static const int register_sizes
[] =
327 1, 1, 1, 1, 1, 1, 1, 1,
328 1, 1, 1, 1, 1, 1, 1, 1,
329 1, 1, 1, 1, 1, 1, 2, 1,
330 1, 1, 1, 1, 1, 1, 1, 1,
334 /* Predicates used in the MD patterns. This one is true when virtual
335 insns may be matched, which typically means before (or during) the
338 rl78_virt_insns_ok (void)
341 return cfun
->machine
->virt_insns_ok
;
345 /* Predicates used in the MD patterns. This one is true when real
346 insns may be matched, which typically means after (or during) the
349 rl78_real_insns_ok (void)
352 return cfun
->machine
->real_insns_ok
;
356 /* Implements HARD_REGNO_NREGS. */
358 rl78_hard_regno_nregs (int regno
, enum machine_mode mode
)
360 int rs
= register_sizes
[regno
];
363 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
366 /* Implements HARD_REGNO_MODE_OK. */
368 rl78_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
370 int s
= GET_MODE_SIZE (mode
);
374 /* These are not to be used by gcc. */
375 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
377 /* $fp can alway sbe accessed as a 16-bit value. */
378 if (regno
== FP_REG
&& s
== 2)
382 /* Since a reg-reg move is really a reg-mem move, we must
383 enforce alignment. */
384 if (s
> 1 && (regno
% 2))
389 return (mode
== BImode
);
390 /* All other registers must be accessed in their natural sizes. */
391 if (s
== register_sizes
[regno
])
396 /* Simplify_gen_subreg() doesn't handle memory references the way we
397 need it to below, so we use this function for when we must get a
398 valid subreg in a "natural" state. */
400 rl78_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
402 if (GET_CODE (r
) == MEM
)
403 return adjust_address (r
, mode
, byte
);
405 return simplify_gen_subreg (mode
, r
, omode
, byte
);
408 /* Used by movsi. Split SImode moves into two HImode moves, using
409 appropriate patterns for the upper and lower halves of symbols. */
411 rl78_expand_movsi (rtx
*operands
)
413 rtx op00
, op02
, op10
, op12
;
415 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
416 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
417 if (GET_CODE (operands
[1]) == CONST
418 || GET_CODE (operands
[1]) == SYMBOL_REF
)
420 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
421 op10
= gen_rtx_CONST (HImode
, op10
);
422 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
423 op12
= gen_rtx_CONST (HImode
, op12
);
427 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
428 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
431 if (rtx_equal_p (operands
[0], operands
[1]))
433 else if (rtx_equal_p (op00
, op12
))
435 emit_move_insn (op02
, op12
);
436 emit_move_insn (op00
, op10
);
440 emit_move_insn (op00
, op10
);
441 emit_move_insn (op02
, op12
);
446 rl78_split_movsi (rtx
*operands
)
448 rtx op00
, op02
, op10
, op12
;
450 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
451 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
452 if (GET_CODE (operands
[1]) == CONST
453 || GET_CODE (operands
[1]) == SYMBOL_REF
)
455 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
456 op10
= gen_rtx_CONST (HImode
, op10
);
457 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
458 op12
= gen_rtx_CONST (HImode
, op12
);
462 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
463 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
466 if (rtx_equal_p (operands
[0], operands
[1]))
468 else if (rtx_equal_p (op00
, op12
))
485 /* Used by various two-operand expanders which cannot accept all
486 operands in the "far" namespace. Force some such operands into
487 registers so that each pattern has at most one far operand. */
489 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
494 /* FIXME: in the future, be smarter about only doing this if the
495 other operand is also far, assuming the devirtualizer can also
497 if (rl78_far_p (operands
[0]))
499 temp_reg
= operands
[0];
500 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
506 emit_insn (gen (operands
[0], operands
[1]));
508 emit_move_insn (temp_reg
, operands
[0]);
512 /* Likewise, but for three-operand expanders. */
514 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
519 /* FIXME: Likewise. */
520 if (rl78_far_p (operands
[1]))
522 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
523 emit_move_insn (temp_reg
, operands
[1]);
524 operands
[1] = temp_reg
;
527 if (rl78_far_p (operands
[0]))
529 temp_reg
= operands
[0];
530 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
536 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
538 emit_move_insn (temp_reg
, operands
[0]);
542 #undef TARGET_CAN_ELIMINATE
543 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
546 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
551 /* Returns true if the given register needs to be saved by the
554 need_to_save (unsigned int regno
)
556 if (is_interrupt_func (cfun
->decl
))
558 /* We don't need to save registers that have
559 been reserved for interrupt handlers. */
563 /* If the handler is a non-leaf function then it may call
564 non-interrupt aware routines which will happily clobber
565 any call_used registers, so we have to preserve them. */
566 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
569 /* Otherwise we only have to save a register, call_used
570 or not, if it is used by this handler. */
571 return df_regs_ever_live_p (regno
);
574 if (regno
== FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
576 if (fixed_regs
[regno
])
578 if (crtl
->calls_eh_return
)
580 if (df_regs_ever_live_p (regno
)
581 && !call_used_regs
[regno
])
586 /* We use this to wrap all emitted insns in the prologue. */
590 RTX_FRAME_RELATED_P (x
) = 1;
594 /* Compute all the frame-related fields in our machine_function
597 rl78_compute_frame_info (void)
601 cfun
->machine
->computed
= 1;
602 cfun
->machine
->framesize_regs
= 0;
603 cfun
->machine
->framesize_locals
= get_frame_size ();
604 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
606 for (i
= 0; i
< 16; i
++)
607 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
609 cfun
->machine
->need_to_push
[i
] = 1;
610 cfun
->machine
->framesize_regs
+= 2;
613 cfun
->machine
->need_to_push
[i
] = 0;
615 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
616 cfun
->machine
->framesize_locals
++;
618 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
619 + cfun
->machine
->framesize_locals
620 + cfun
->machine
->framesize_outgoing
);
623 /* Returns true if the provided function has the specified attribute. */
625 has_func_attr (const_tree decl
, const char * func_attr
)
627 if (decl
== NULL_TREE
)
628 decl
= current_function_decl
;
630 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
633 /* Returns true if the provided function has the "interrupt" attribute. */
635 is_interrupt_func (const_tree decl
)
637 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
640 /* Returns true if the provided function has the "brk_interrupt" attribute. */
642 is_brk_interrupt_func (const_tree decl
)
644 return has_func_attr (decl
, "brk_interrupt");
647 /* Check "interrupt" attributes. */
649 rl78_handle_func_attribute (tree
* node
,
652 int flags ATTRIBUTE_UNUSED
,
655 gcc_assert (DECL_P (* node
));
656 gcc_assert (args
== NULL_TREE
);
658 if (TREE_CODE (* node
) != FUNCTION_DECL
)
660 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
662 * no_add_attrs
= true;
665 /* FIXME: We ought to check that the interrupt and exception
666 handler attributes have been applied to void functions. */
670 #undef TARGET_ATTRIBUTE_TABLE
671 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
673 /* Table of RL78-specific attributes. */
674 const struct attribute_spec rl78_attribute_table
[] =
676 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
677 affects_type_identity. */
678 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
680 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
682 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute
,
684 { NULL
, 0, 0, false, false, false, NULL
, false }
689 /* Break down an address RTX into its component base/index/addend
690 portions and return TRUE if the address is of a valid form, else
693 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
699 if (GET_CODE (x
) == REG
)
705 /* We sometimes get these without the CONST wrapper */
706 if (GET_CODE (x
) == PLUS
707 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
708 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
714 if (GET_CODE (x
) == PLUS
)
719 if (GET_CODE (*base
) != REG
720 && GET_CODE (x
) == REG
)
727 if (GET_CODE (*base
) != REG
)
730 if (GET_CODE (x
) == ZERO_EXTEND
731 && GET_CODE (XEXP (x
, 0)) == REG
)
733 *index
= XEXP (x
, 0);
738 switch (GET_CODE (x
))
741 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
742 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
765 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
768 rl78_hl_b_c_addr_p (rtx op
)
772 if (GET_CODE (op
) != PLUS
)
776 if (GET_CODE (hl
) == ZERO_EXTEND
)
782 if (GET_CODE (hl
) != REG
)
784 if (GET_CODE (bc
) != ZERO_EXTEND
)
787 if (GET_CODE (bc
) != REG
)
789 if (REGNO (hl
) != HL_REG
)
791 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
797 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
799 /* Used in various constraints and predicates to match operands in the
800 "far" address space. */
807 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx(x
);
808 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
810 return MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
;
813 /* Return the appropriate mode for a named address pointer. */
814 #undef TARGET_ADDR_SPACE_POINTER_MODE
815 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
816 static enum machine_mode
817 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
821 case ADDR_SPACE_GENERIC
:
830 /* Returns TRUE for valid addresses. */
831 #undef TARGET_VALID_POINTER_MODE
832 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
834 rl78_valid_pointer_mode (enum machine_mode m
)
836 return (m
== HImode
|| m
== SImode
);
839 /* Return the appropriate mode for a named address address. */
840 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
841 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
842 static enum machine_mode
843 rl78_addr_space_address_mode (addr_space_t addrspace
)
847 case ADDR_SPACE_GENERIC
:
856 #undef TARGET_LEGITIMATE_CONSTANT_P
857 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
860 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
865 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
866 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
869 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
870 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
872 rtx base
, index
, addend
;
874 if (GET_CODE (x
) == UNSPEC
875 && XINT (x
, 1) == UNS_ES_ADDR
)
876 x
= XVECEXP (x
, 0, 1);
878 if (as
== ADDR_SPACE_GENERIC
879 && GET_MODE (x
) == SImode
)
882 if (! characterize_address (x
, &base
, &index
, &addend
))
885 /* We can't extract the high/low portions of a PLUS address
886 involving a register during devirtualization, so make sure all
887 such __far addresses do not have addends. This forces GCC to do
888 the sum separately. */
889 if (addend
&& base
&& as
== ADDR_SPACE_FAR
)
894 int ir
= REGNO (index
);
895 int br
= REGNO (base
);
897 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
898 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
899 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
903 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
906 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
907 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
913 /* Determine if one named address space is a subset of another. */
914 #undef TARGET_ADDR_SPACE_SUBSET_P
915 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
917 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
919 gcc_assert (subset
== ADDR_SPACE_GENERIC
|| subset
== ADDR_SPACE_FAR
);
920 gcc_assert (superset
== ADDR_SPACE_GENERIC
|| superset
== ADDR_SPACE_FAR
);
922 if (subset
== superset
)
926 return (subset
== ADDR_SPACE_GENERIC
&& superset
== ADDR_SPACE_FAR
);
929 #undef TARGET_ADDR_SPACE_CONVERT
930 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
931 /* Convert from one address space to another. */
933 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
935 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
936 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
939 gcc_assert (from_as
== ADDR_SPACE_GENERIC
|| from_as
== ADDR_SPACE_FAR
);
940 gcc_assert (to_as
== ADDR_SPACE_GENERIC
|| to_as
== ADDR_SPACE_FAR
);
942 if (to_as
== ADDR_SPACE_GENERIC
&& from_as
== ADDR_SPACE_FAR
)
944 /* This is unpredictable, as we're truncating off usable address
947 result
= gen_reg_rtx (HImode
);
948 emit_move_insn (result
, simplify_subreg (HImode
, op
, SImode
, 0));
951 else if (to_as
== ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_GENERIC
)
953 /* This always works. */
954 result
= gen_reg_rtx (SImode
);
955 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
956 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
963 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
965 rl78_regno_mode_code_ok_for_base_p (int regno
, enum machine_mode mode ATTRIBUTE_UNUSED
,
966 addr_space_t address_space ATTRIBUTE_UNUSED
,
967 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
969 if (regno
<= SP_REG
&& regno
>= 16)
971 if (index_code
== REG
)
972 return (regno
== HL_REG
);
973 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
978 /* Implements MODE_CODE_BASE_REG_CLASS. */
980 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED
,
981 addr_space_t address_space ATTRIBUTE_UNUSED
,
982 int outer_code ATTRIBUTE_UNUSED
,
983 int index_code ATTRIBUTE_UNUSED
)
988 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
989 described in the machine_Function struct definition, above. */
991 rl78_initial_elimination_offset (int from
, int to
)
993 int rv
= 0; /* as if arg to arg */
995 rl78_compute_frame_info ();
999 case STACK_POINTER_REGNUM
:
1000 rv
+= cfun
->machine
->framesize_outgoing
;
1001 rv
+= cfun
->machine
->framesize_locals
;
1003 case FRAME_POINTER_REGNUM
:
1004 rv
+= cfun
->machine
->framesize_regs
;
1013 case FRAME_POINTER_REGNUM
:
1015 rv
-= cfun
->machine
->framesize_regs
;
1016 case ARG_POINTER_REGNUM
:
1026 rl78_is_naked_func (void)
1028 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1031 /* Expand the function prologue (from the prologue pattern). */
1033 rl78_expand_prologue (void)
1036 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1039 if (rl78_is_naked_func ())
1042 /* Always re-compute the frame info - the register usage may have changed. */
1043 rl78_compute_frame_info ();
1045 if (flag_stack_usage_info
)
1046 current_function_static_stack_size
= cfun
->machine
->framesize
;
1048 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1049 for (i
= 0; i
< 4; i
++)
1050 if (cfun
->machine
->need_to_push
[i
])
1052 /* Select Bank 0 if we are using any registers from Bank 0. */
1053 emit_insn (gen_sel_rb (GEN_INT (0)));
1057 for (i
= 0; i
< 16; i
++)
1058 if (cfun
->machine
->need_to_push
[i
])
1062 emit_move_insn (gen_rtx_REG (HImode
, 0), gen_rtx_REG (HImode
, i
*2));
1063 F (emit_insn (gen_push (gen_rtx_REG (HImode
, 0))));
1066 int need_bank
= i
/4;
1067 if (need_bank
!= rb
)
1069 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1072 F (emit_insn (gen_push (gen_rtx_REG (HImode
, i
*2))));
1076 emit_insn (gen_sel_rb (GEN_INT (0)));
1078 if (frame_pointer_needed
)
1080 F (emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1081 gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
)));
1082 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
),
1083 gen_rtx_REG (HImode
, AX_REG
)));
1086 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1089 int fs_byte
= (fs
> 254) ? 254 : fs
;
1090 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1095 /* Expand the function epilogue (from the epilogue pattern). */
1097 rl78_expand_epilogue (void)
1100 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1103 if (rl78_is_naked_func ())
1106 if (frame_pointer_needed
)
1108 emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1109 gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1110 emit_move_insn (gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
),
1111 gen_rtx_REG (HImode
, AX_REG
));
1115 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1118 int fs_byte
= (fs
> 254) ? 254 : fs
;
1120 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1125 for (i
= 15; i
>= 0; i
--)
1126 if (cfun
->machine
->need_to_push
[i
])
1130 emit_insn (gen_pop (gen_rtx_REG (HImode
, 0)));
1131 emit_move_insn (gen_rtx_REG (HImode
, i
*2), gen_rtx_REG (HImode
, 0));
1135 int need_bank
= i
/ 4;
1137 if (need_bank
!= rb
)
1139 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1142 emit_insn (gen_pop (gen_rtx_REG (HImode
, i
* 2)));
1147 emit_insn (gen_sel_rb (GEN_INT (0)));
1149 if (cfun
->machine
->trampolines_used
)
1150 emit_insn (gen_trampoline_uninit ());
1152 if (is_brk_interrupt_func (cfun
->decl
))
1153 emit_jump_insn (gen_brk_interrupt_return ());
1154 else if (is_interrupt_func (cfun
->decl
))
1155 emit_jump_insn (gen_interrupt_return ());
1157 emit_jump_insn (gen_rl78_return ());
1160 /* Likewise, for exception handlers. */
1162 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1164 /* FIXME - replace this with an indirect jump with stack adjust. */
1165 emit_jump_insn (gen_rl78_return ());
1168 #undef TARGET_ASM_FUNCTION_PROLOGUE
1169 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1171 /* We don't use this to actually emit the function prologue. We use
1172 this to insert a comment in the asm file describing the
1175 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1179 if (cfun
->machine
->framesize
== 0)
1181 fprintf (file
, "\t; start of function\n");
1183 if (cfun
->machine
->framesize_regs
)
1185 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1186 for (i
= 0; i
< 16; i
++)
1187 if (cfun
->machine
->need_to_push
[i
])
1188 fprintf (file
, " %s", word_regnames
[i
*2]);
1189 fprintf (file
, "\n");
1192 if (frame_pointer_needed
)
1193 fprintf (file
, "\t; $fp points here (r22)\n");
1195 if (cfun
->machine
->framesize_locals
)
1196 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1197 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1199 if (cfun
->machine
->framesize_outgoing
)
1200 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1201 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1204 /* Return an RTL describing where a function return value of type RET_TYPE
1207 #undef TARGET_FUNCTION_VALUE
1208 #define TARGET_FUNCTION_VALUE rl78_function_value
1211 rl78_function_value (const_tree ret_type
,
1212 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1213 bool outgoing ATTRIBUTE_UNUSED
)
1215 enum machine_mode mode
= TYPE_MODE (ret_type
);
1217 return gen_rtx_REG (mode
, 8);
1220 #undef TARGET_PROMOTE_FUNCTION_MODE
1221 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1223 static enum machine_mode
1224 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1225 enum machine_mode mode
,
1226 int *punsignedp ATTRIBUTE_UNUSED
,
1227 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1232 /* Return an RTL expression describing the register holding a function
1233 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1234 be passed on the stack. CUM describes the previous parameters to the
1235 function and NAMED is false if the parameter is part of a variable
1236 parameter list, or the last named parameter before the start of a
1237 variable parameter list. */
1239 #undef TARGET_FUNCTION_ARG
1240 #define TARGET_FUNCTION_ARG rl78_function_arg
1243 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1244 enum machine_mode mode ATTRIBUTE_UNUSED
,
1245 const_tree type ATTRIBUTE_UNUSED
,
1246 bool named ATTRIBUTE_UNUSED
)
1251 #undef TARGET_FUNCTION_ARG_ADVANCE
1252 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1255 rl78_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
, const_tree type
,
1256 bool named ATTRIBUTE_UNUSED
)
1259 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1261 rounded_size
= ((mode
== BLKmode
)
1262 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1263 if (rounded_size
& 1)
1265 (*cum
) += rounded_size
;
1268 #undef TARGET_FUNCTION_ARG_BOUNDARY
1269 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1272 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED
,
1273 const_tree type ATTRIBUTE_UNUSED
)
1278 /* Supported modifier letters:
1280 A - address of a MEM
1281 S - SADDR form of a real register
1282 v - real register corresponding to a virtual register
1283 m - minus - negative of CONST_INT value.
1284 c - inverse of a conditional (NE vs EQ for example)
1285 z - collapsed conditional
1286 s - shift count mod 8
1287 S - shift count mod 16
1288 r - reverse shift count (8-(count mod 8))
1290 h - bottom HI of an SI
1292 q - bottom QI of an HI
1294 e - third QI of an SI (i.e. where the ES register gets values from)
1295 E - fourth QI of an SI (i.e. MSB)
1299 /* Implements the bulk of rl78_print_operand, below. We do it this
1300 way because we need to test for a constant at the top level and
1301 insert the '#', but not test for it anywhere else as we recurse
1302 down into the operand. */
1304 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1308 switch (GET_CODE (op
))
1312 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1315 if (rl78_far_p (op
))
1317 fprintf (file
, "es:");
1318 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1322 op
= adjust_address (op
, HImode
, 2);
1327 op
= adjust_address (op
, HImode
, 0);
1332 op
= adjust_address (op
, QImode
, 1);
1337 op
= adjust_address (op
, QImode
, 0);
1342 op
= adjust_address (op
, QImode
, 2);
1347 op
= adjust_address (op
, QImode
, 3);
1350 if (CONSTANT_P (XEXP (op
, 0)))
1352 fprintf (file
, "!");
1353 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1355 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1356 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1358 fprintf (file
, "!");
1359 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1361 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1362 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1363 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1365 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1366 fprintf (file
, "[");
1367 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1368 fprintf (file
, "]");
1372 fprintf (file
, "[");
1373 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1374 fprintf (file
, "]");
1381 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1382 else if (letter
== 'H')
1383 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1384 else if (letter
== 'q')
1385 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1386 else if (letter
== 'e')
1387 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1388 else if (letter
== 'E')
1389 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1390 else if (letter
== 'S')
1391 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1392 else if (GET_MODE (op
) == HImode
1393 && ! (REGNO (op
) & ~0xfe))
1396 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1398 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1401 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1406 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1407 else if (letter
== 'H')
1408 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1409 else if (letter
== 'q')
1410 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1411 else if (letter
== 'h')
1412 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1413 else if (letter
== 'e')
1414 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1415 else if (letter
== 'E')
1416 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1417 else if (letter
== 'm')
1418 fprintf (file
, "%ld", - INTVAL (op
));
1419 else if (letter
== 's')
1420 fprintf (file
, "%ld", INTVAL (op
) % 8);
1421 else if (letter
== 'S')
1422 fprintf (file
, "%ld", INTVAL (op
) % 16);
1423 else if (letter
== 'r')
1424 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1425 else if (letter
== 'C')
1426 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1428 fprintf (file
, "%ld", INTVAL (op
));
1432 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1437 int bits
= INTVAL (XEXP (op
, 1));
1438 int ofs
= INTVAL (XEXP (op
, 2));
1439 if (bits
== 16 && ofs
== 0)
1440 fprintf (file
, "%%lo16(");
1441 else if (bits
== 16 && ofs
== 16)
1442 fprintf (file
, "%%hi16(");
1443 else if (bits
== 8 && ofs
== 16)
1444 fprintf (file
, "%%hi8(");
1447 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1448 fprintf (file
, ")");
1453 if (GET_CODE (XEXP (op
, 0)) == REG
)
1454 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1456 print_rtl (file
, op
);
1463 fprintf (file
, "%%hi16(");
1469 fprintf (file
, "%%lo16(");
1475 fprintf (file
, "%%hi8(");
1479 if (letter
== 'q' || letter
== 'Q')
1480 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1482 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1484 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1485 fprintf (file
, "+");
1486 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1490 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1491 fprintf (file
, "+");
1492 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1495 fprintf (file
, ")");
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 output_addr_const (file
, op
);
1523 fprintf (file
, ")");
1528 output_asm_label (op
);
1533 fprintf (file
, "#comparison eliminated");
1535 fprintf (file
, letter
== 'c' ? "nc" : "c");
1539 fprintf (file
, "br");
1541 fprintf (file
, letter
== 'c' ? "h" : "nh");
1545 fprintf (file
, "br");
1547 fprintf (file
, letter
== 'c' ? "c" : "nc");
1551 fprintf (file
, "#comparison eliminated");
1553 fprintf (file
, letter
== 'c' ? "nh" : "h");
1557 fprintf (file
, "br");
1559 fprintf (file
, letter
== 'c' ? "nz" : "z");
1563 fprintf (file
, "#comparison eliminated");
1565 fprintf (file
, letter
== 'c' ? "z" : "nz");
1568 /* Note: these assume appropriate adjustments were made so that
1569 unsigned comparisons, which is all this chip has, will
1573 fprintf (file
, "#comparison eliminated");
1575 fprintf (file
, letter
== 'c' ? "nc" : "c");
1579 fprintf (file
, "br");
1581 fprintf (file
, letter
== 'c' ? "h" : "nh");
1585 fprintf (file
, "br");
1587 fprintf (file
, letter
== 'c' ? "c" : "nc");
1591 fprintf (file
, "#comparison eliminated");
1593 fprintf (file
, letter
== 'c' ? "nh" : "h");
1597 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1602 #undef TARGET_PRINT_OPERAND
1603 #define TARGET_PRINT_OPERAND rl78_print_operand
1606 rl78_print_operand (FILE * file
, rtx op
, int letter
)
1608 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S')
1609 fprintf (file
, "#");
1610 rl78_print_operand_1 (file
, op
, letter
);
1613 #undef TARGET_TRAMPOLINE_INIT
1614 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1616 /* Note that the RL78's addressing makes it very difficult to do
1617 trampolines on the stack. So, libgcc has a small pool of
1618 trampolines from which one is allocated to this task. */
1620 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
1622 rtx mov_addr
, thunk_addr
;
1623 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
1625 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
1626 thunk_addr
= gen_reg_rtx (HImode
);
1628 function
= force_reg (HImode
, function
);
1629 static_chain
= force_reg (HImode
, static_chain
);
1631 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
1632 emit_move_insn (mov_addr
, thunk_addr
);
1634 cfun
->machine
->trampolines_used
= 1;
1637 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1638 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1641 rl78_trampoline_adjust_address (rtx m_tramp
)
1643 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
1647 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1648 the "normal" compares, specifically, it only has unsigned compares,
1649 so we must synthesize the missing ones. */
1651 rl78_expand_compare (rtx
*operands
)
1653 if (GET_CODE (operands
[2]) == MEM
)
1654 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
1659 /* Define this to 1 if you are debugging the peephole optimizers. */
1660 #define DEBUG_PEEP 0
1662 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1663 The default "word" size is a byte so we can effectively use all the
1664 registers, but we want to do 16-bit moves whenever possible. This
1665 function determines when such a move is an option. */
1667 rl78_peep_movhi_p (rtx
*operands
)
1672 /* (set (op0) (op1))
1673 (set (op2) (op3)) */
1676 fprintf (stderr
, "\033[33m");
1677 debug_rtx (operands
[0]);
1678 debug_rtx (operands
[1]);
1679 debug_rtx (operands
[2]);
1680 debug_rtx (operands
[3]);
1681 fprintf (stderr
, "\033[0m");
1684 /* You can move a constant to memory as QImode, but not HImode. */
1685 if (GET_CODE (operands
[0]) == MEM
1686 && GET_CODE (operands
[1]) != REG
)
1689 fprintf (stderr
, "no peep: move constant to memory\n");
1694 if (rtx_equal_p (operands
[0], operands
[3]))
1697 fprintf (stderr
, "no peep: overlapping\n");
1702 for (i
= 0; i
< 2; i
++)
1704 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
1707 fprintf (stderr
, "no peep: different codes\n");
1711 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
1714 fprintf (stderr
, "no peep: different modes\n");
1719 switch (GET_CODE (operands
[i
]))
1723 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
1724 || GET_MODE (operands
[i
]) != QImode
)
1727 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
1728 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
1733 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
1736 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
1746 if (GET_MODE (operands
[i
]) != QImode
)
1748 if (MEM_ALIGN (operands
[i
]) < 16)
1750 a
= XEXP (operands
[i
], 0);
1751 if (GET_CODE (a
) == CONST
)
1753 if (GET_CODE (a
) == PLUS
)
1755 if (GET_CODE (a
) == CONST_INT
1759 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
1760 debug_rtx (operands
[i
]);
1764 m
= adjust_address (operands
[i
], QImode
, 1);
1765 if (! rtx_equal_p (m
, operands
[i
+2]))
1768 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
1770 debug_rtx (operands
[i
+2]);
1778 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
1784 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
1789 /* Likewise, when a peephole is activated, this function helps compute
1790 the new operands. */
1792 rl78_setup_peep_movhi (rtx
*operands
)
1796 for (i
= 0; i
< 2; i
++)
1798 switch (GET_CODE (operands
[i
]))
1801 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
1805 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char)INTVAL (operands
[i
+2])) * 256);
1809 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
1819 How Devirtualization works in the RL78 GCC port
1823 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1824 bytes of register space, in four banks, memory-mapped. One bank is
1825 the "selected" bank and holds the registers used for primary
1826 operations. Since the registers are memory mapped, often you can
1827 still refer to the unselected banks via memory accesses.
1831 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1832 and refers to the other banks via their memory addresses, although
1833 they're treated as regular registers internally. These "virtual"
1834 registers are R8 through R23 (bank3 is reserved for asm-based
1835 interrupt handlers).
1837 There are four machine description files:
1839 rl78.md - common register-independent patterns and definitions
1840 rl78-expand.md - expanders
1841 rl78-virt.md - patterns that match BEFORE devirtualization
1842 rl78-real.md - patterns that match AFTER devirtualization
1844 At least through register allocation and reload, gcc is told that it
1845 can do pretty much anything - but may only use the virtual registers.
1846 GCC cannot properly create the varying addressing modes that the RL78
1847 supports in an efficient way.
1849 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1850 uses the "valloc" attribute in rl78-virt.md for determining the rules
1851 by which it will replace virtual registers with real registers (or
1852 not) and how to make up addressing modes. For example, insns tagged
1853 with "ro1" have a single read-only parameter, which may need to be
1854 moved from memory/constant/vreg to a suitable real register. As part
1855 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1856 patterns and enabling the rl78-real.md patterns. The new patterns'
1857 constraints are used to determine the real registers used. NOTE:
1858 patterns in rl78-virt.md essentially ignore the constrains and rely on
1859 predicates, where the rl78-real.md ones essentially ignore the
1860 predicates and rely on the constraints.
1862 The devirtualization pass is scheduled via the pass manager (despite
1863 being called "rl78_reorg") so it can be scheduled prior to var-track
1864 (the idea is to let gdb know about the new registers). Ideally, it
1865 would be scheduled right after pro/epilogue generation, so the
1866 post-reload optimizers could operate on the real registers, but when I
1867 tried that there were some issues building the target libraries.
1869 During devirtualization, a simple register move optimizer is run. It
1870 would be better to run a full CSE/propogation pass on it through, or
1871 re-run regmove, but that has not yet been attempted.
1874 #define DEBUG_ALLOC 0
1876 #define OP(x) (*recog_data.operand_loc[x])
1878 /* This array is used to hold knowledge about the contents of the
1879 real registers (A ... H), the memory-based registers (r8 ... r31)
1880 and the first NUM_STACK_LOCS words on the stack. We use this to
1881 avoid generating redundant move instructions.
1883 A value in the range 0 .. 31 indicates register A .. r31.
1884 A value in the range 32 .. 63 indicates stack slot (value - 32).
1885 A value of NOT_KNOWN indicates that the contents of that location
1888 #define NUM_STACK_LOCS 32
1889 #define NOT_KNOWN 127
1891 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
1893 static unsigned char saved_update_index
= NOT_KNOWN
;
1894 static unsigned char saved_update_value
;
1895 static enum machine_mode saved_update_mode
;
1899 clear_content_memory (void)
1901 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
1903 fprintf (dump_file
, " clear content memory\n");
1904 saved_update_index
= NOT_KNOWN
;
1907 /* Convert LOC into an index into the content_memory array.
1908 If LOC cannot be converted, return NOT_KNOWN. */
1910 static unsigned char
1911 get_content_index (rtx loc
)
1913 enum machine_mode mode
;
1915 if (loc
== NULL_RTX
)
1920 if (REGNO (loc
) < 32)
1925 mode
= GET_MODE (loc
);
1927 if (! rl78_stack_based_mem (loc
, mode
))
1930 loc
= XEXP (loc
, 0);
1933 /* loc = MEM (SP) */
1936 /* loc = MEM (PLUS (SP, INT)). */
1937 loc
= XEXP (loc
, 1);
1939 if (INTVAL (loc
) < NUM_STACK_LOCS
)
1940 return 32 + INTVAL (loc
);
1945 /* Return a string describing content INDEX in mode MODE.
1946 WARNING: Can return a pointer to a static buffer. */
1949 get_content_name (unsigned char index
, enum machine_mode mode
)
1951 static char buffer
[128];
1953 if (index
== NOT_KNOWN
)
1957 sprintf (buffer
, "stack slot %d", index
- 32);
1958 else if (mode
== HImode
)
1959 sprintf (buffer
, "%s%s",
1960 reg_names
[index
+ 1], reg_names
[index
]);
1962 return reg_names
[index
];
1970 display_content_memory (FILE * file
)
1974 fprintf (file
, " Known memory contents:\n");
1976 for (i
= 0; i
< sizeof content_memory
; i
++)
1977 if (content_memory
[i
] != NOT_KNOWN
)
1979 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
1980 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
1986 update_content (unsigned char index
, unsigned char val
, enum machine_mode mode
)
1990 gcc_assert (index
< sizeof content_memory
);
1992 content_memory
[index
] = val
;
1993 if (val
!= NOT_KNOWN
)
1994 content_memory
[val
] = index
;
1996 /* Make the entry in dump_file *before* VAL is increased below. */
1999 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2000 if (val
== NOT_KNOWN
)
2001 fprintf (dump_file
, "Unknown\n");
2003 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2008 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2010 content_memory
[index
+ 1] = val
;
2011 if (val
!= NOT_KNOWN
)
2013 content_memory
[val
] = index
+ 1;
2018 /* Any other places that had INDEX recorded as their contents are now invalid. */
2019 for (i
= 0; i
< sizeof content_memory
; i
++)
2022 || (val
!= NOT_KNOWN
&& i
== val
))
2029 if (content_memory
[i
] == index
2030 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2032 content_memory
[i
] = NOT_KNOWN
;
2035 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2038 content_memory
[++ i
] = NOT_KNOWN
;
2043 /* Record that LOC contains VALUE.
2044 For HImode locations record that LOC+1 contains VALUE+1.
2045 If LOC is not a register or stack slot, do nothing.
2046 If VALUE is not a register or stack slot, clear the recorded content. */
2049 record_content (rtx loc
, rtx value
)
2051 enum machine_mode mode
;
2052 unsigned char index
;
2055 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2058 val
= get_content_index (value
);
2060 mode
= GET_MODE (loc
);
2067 /* This should not happen when optimizing. */
2069 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2070 get_content_name (val
, mode
));
2077 update_content (index
, val
, mode
);
2080 /* Returns TRUE if LOC already contains a copy of VALUE. */
2083 already_contains (rtx loc
, rtx value
)
2085 unsigned char index
;
2088 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2091 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2094 if (content_memory
[index
] != val
)
2097 if (GET_MODE (loc
) == HImode
)
2098 return content_memory
[index
+ 1] == val
+ 1;
2104 rl78_es_addr (rtx addr
)
2106 if (GET_CODE (addr
) == MEM
)
2107 addr
= XEXP (addr
, 0);
2108 if (GET_CODE (addr
) != UNSPEC
)
2110 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2116 rl78_es_base (rtx addr
)
2118 if (GET_CODE (addr
) == MEM
)
2119 addr
= XEXP (addr
, 0);
2120 addr
= XVECEXP (addr
, 0, 1);
2121 if (GET_CODE (addr
) == CONST
2122 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2123 addr
= XEXP (XEXP (addr
, 0), 0);
2124 /* Mode doesn't matter here. */
2125 return gen_rtx_MEM (HImode
, addr
);
2128 /* Rescans an insn to see if it's recognized again. This is done
2129 carefully to ensure that all the constraint information is accurate
2130 for the newly matched insn. */
2132 insn_ok_now (rtx insn
)
2134 rtx pattern
= PATTERN (insn
);
2137 INSN_CODE (insn
) = -1;
2139 if (recog (pattern
, insn
, 0) > -1)
2141 extract_insn (insn
);
2142 if (constrain_operands (1))
2145 fprintf (stderr
, "\033[32m");
2147 fprintf (stderr
, "\033[0m");
2149 if (SET_P (pattern
))
2150 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2152 /* We need to detect far addresses that haven't been
2153 converted to es/lo16 format. */
2154 for (i
=0; i
<recog_data
.n_operands
; i
++)
2155 if (GET_CODE (OP(i
)) == MEM
2156 && GET_MODE (XEXP (OP(i
), 0)) == SImode
2157 && GET_CODE (XEXP (OP(i
), 0)) != UNSPEC
)
2165 /* We need to re-recog the insn with virtual registers to get
2167 cfun
->machine
->virt_insns_ok
= 1;
2168 if (recog (pattern
, insn
, 0) > -1)
2170 extract_insn (insn
);
2171 if (constrain_operands (0))
2173 cfun
->machine
->virt_insns_ok
= 0;
2179 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2186 fprintf (stderr
, "\033[31m");
2188 fprintf (stderr
, "\033[0m");
2194 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2195 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2196 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2197 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2198 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2200 #define FAILED gcc_unreachable ()
2201 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2202 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2205 /* Registers into which we move the contents of virtual registers. */
2206 #define X gen_rtx_REG (QImode, 0)
2207 #define A gen_rtx_REG (QImode, 1)
2208 #define C gen_rtx_REG (QImode, 2)
2209 #define B gen_rtx_REG (QImode, 3)
2210 #define E gen_rtx_REG (QImode, 4)
2211 #define D gen_rtx_REG (QImode, 5)
2212 #define L gen_rtx_REG (QImode, 6)
2213 #define H gen_rtx_REG (QImode, 7)
2215 #define AX gen_rtx_REG (HImode, 0)
2216 #define BC gen_rtx_REG (HImode, 2)
2217 #define DE gen_rtx_REG (HImode, 4)
2218 #define HL gen_rtx_REG (HImode, 6)
2220 /* Returns TRUE if R is a virtual register. */
2222 is_virtual_register (rtx r
)
2224 return (GET_CODE (r
) == REG
2229 /* In all these alloc routines, we expect the following: the insn
2230 pattern is unshared, the insn was previously recognized and failed
2231 due to predicates or constraints, and the operand data is in
2234 static int virt_insn_was_frame
;
2236 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2239 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2242 fprintf (stderr
, "\033[36m%d: ", line
);
2244 fprintf (stderr
, "\033[0m");
2246 /*SCHED_GROUP_P (r) = 1;*/
2247 if (virt_insn_was_frame
)
2248 RTX_FRAME_RELATED_P (r
) = 1;
2252 #define EM(x) EM2 (__LINE__, x)
2254 /* Return a suitable RTX for the low half of a __far address. */
2256 rl78_lo16 (rtx addr
)
2260 if (GET_CODE (addr
) == SYMBOL_REF
2261 || GET_CODE (addr
) == CONST
)
2263 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2264 r
= gen_rtx_CONST (HImode
, r
);
2267 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2269 r
= gen_es_addr (r
);
2274 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2278 if (GET_CODE (addr
) == SYMBOL_REF
2279 || GET_CODE (addr
) == CONST
)
2281 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2282 r
= gen_rtx_CONST (QImode
, r
);
2285 return rl78_subreg (QImode
, addr
, SImode
, 2);
2289 add_postponed_content_update (rtx to
, rtx value
)
2291 unsigned char index
;
2293 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2296 gcc_assert (saved_update_index
== NOT_KNOWN
);
2297 saved_update_index
= index
;
2298 saved_update_value
= get_content_index (value
);
2299 saved_update_mode
= GET_MODE (to
);
2303 process_postponed_content_update (void)
2305 if (saved_update_index
!= NOT_KNOWN
)
2307 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2308 saved_update_index
= NOT_KNOWN
;
2312 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2313 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2314 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2315 BEFORE is true, FROM otherwise. */
2317 gen_and_emit_move (rtx to
, rtx from
, rtx where
, bool before
)
2319 enum machine_mode mode
= GET_MODE (to
);
2321 if (optimize
&& before
&& already_contains (to
, from
))
2324 display_content_memory (stderr
);
2328 fprintf (dump_file
, " Omit move of %s into ",
2329 get_content_name (get_content_index (from
), mode
));
2330 fprintf (dump_file
, "%s as it already contains this value\n",
2331 get_content_name (get_content_index (to
), mode
));
2336 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2340 if (where
== NULL_RTX
)
2343 emit_insn_before (move
, where
);
2346 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2348 /* If necessary move REG_EH_REGION notes forward.
2349 cf. compiling gcc.dg/pr44545.c. */
2350 if (note
!= NULL_RTX
)
2352 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2353 remove_note (where
, note
);
2356 emit_insn_after (move
, where
);
2360 record_content (to
, from
);
2362 add_postponed_content_update (to
, from
);
2364 return before
? to
: from
;
2367 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2368 copy it into NEWBASE and return the updated MEM. Otherwise just
2369 return M. Any needed insns are emitted before BEFORE. */
2371 transcode_memory_rtx (rtx m
, rtx newbase
, rtx before
)
2373 rtx base
, index
, addendr
;
2380 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2382 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2384 fprintf (stderr
, "setting ES:\n");
2387 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2388 emit_insn_before (EM (gen_movqi_es (A
)), before
);
2389 record_content (A
, NULL_RTX
);
2391 m
= change_address (m
, GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2395 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2396 gcc_assert (index
== NULL_RTX
);
2399 fprintf (stderr
, "\033[33m"); debug_rtx (m
); fprintf (stderr
, "\033[0m");
2402 if (base
== NULL_RTX
)
2405 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2406 addend
= INTVAL (addendr
);
2408 gcc_assert (REG_P (base
));
2409 gcc_assert (REG_P (newbase
));
2411 if (REGNO (base
) == SP_REG
)
2413 if (addend
>= 0 && addend
<= 255)
2417 /* BASE should be a virtual register. We copy it to NEWBASE. If
2418 the addend is out of range for DE/HL, we use AX to compute the full
2422 || (addend
> 255 && REGNO (newbase
) != 2)
2423 || (addendr
&& GET_CODE (addendr
) != CONST_INT
))
2428 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2429 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2430 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2431 record_content (AX
, NULL_RTX
);
2432 record_content (newbase
, NULL_RTX
);
2439 base
= gen_and_emit_move (newbase
, base
, before
, true);
2444 record_content (base
, NULL_RTX
);
2445 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2449 fprintf (stderr
, "\033[33m");
2453 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2455 m
= change_address (m
, GET_MODE (m
), base
);
2458 fprintf (stderr
, "\033[0m");
2463 /* Copy SRC to accumulator (A or AX), placing any generated insns
2464 before BEFORE. Returns accumulator RTX. */
2467 move_to_acc (int opno
, rtx before
)
2469 rtx src
= OP (opno
);
2470 enum machine_mode mode
= GET_MODE (src
);
2472 if (REG_P (src
) && REGNO (src
) < 2)
2475 if (mode
== VOIDmode
)
2476 mode
= recog_data
.operand_mode
[opno
];
2478 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2482 force_into_acc (rtx src
, rtx before
)
2484 enum machine_mode mode
= GET_MODE (src
);
2487 if (REG_P (src
) && REGNO (src
) < 2)
2490 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2494 emit_insn_before (move
, before
);
2495 record_content (AX
, NULL_RTX
);
2498 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2499 after AFTER. Returns accumulator RTX. */
2502 move_from_acc (unsigned int opno
, rtx after
)
2504 rtx dest
= OP (opno
);
2505 enum machine_mode mode
= GET_MODE (dest
);
2507 if (REG_P (dest
) && REGNO (dest
) < 2)
2510 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2513 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2514 before BEFORE. Returns reg RTX. */
2517 move_acc_to_reg (rtx acc
, int regno
, rtx before
)
2519 enum machine_mode mode
= GET_MODE (acc
);
2522 reg
= gen_rtx_REG (mode
, regno
);
2524 return gen_and_emit_move (reg
, acc
, before
, true);
2527 /* Copy SRC to X, placing any generated insns before BEFORE.
2531 move_to_x (int opno
, rtx before
)
2533 rtx src
= OP (opno
);
2534 enum machine_mode mode
= GET_MODE (src
);
2537 if (mode
== VOIDmode
)
2538 mode
= recog_data
.operand_mode
[opno
];
2539 reg
= (mode
== QImode
) ? X
: AX
;
2541 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2543 OP (opno
) = move_to_acc (opno
, before
);
2544 OP (opno
) = move_acc_to_reg (OP(opno
), X_REG
, before
);
2548 return gen_and_emit_move (reg
, src
, before
, true);
2551 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
2552 Returns H/HL RTX. */
2555 move_to_hl (int opno
, rtx before
)
2557 rtx src
= OP (opno
);
2558 enum machine_mode mode
= GET_MODE (src
);
2561 if (mode
== VOIDmode
)
2562 mode
= recog_data
.operand_mode
[opno
];
2563 reg
= (mode
== QImode
) ? L
: HL
;
2565 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2567 OP (opno
) = move_to_acc (opno
, before
);
2568 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
2572 return gen_and_emit_move (reg
, src
, before
, true);
2575 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
2576 Returns E/DE RTX. */
2579 move_to_de (int opno
, rtx before
)
2581 rtx src
= OP (opno
);
2582 enum machine_mode mode
= GET_MODE (src
);
2585 if (mode
== VOIDmode
)
2586 mode
= recog_data
.operand_mode
[opno
];
2588 reg
= (mode
== QImode
) ? E
: DE
;
2590 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2592 OP (opno
) = move_to_acc (opno
, before
);
2593 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
2597 gen_and_emit_move (reg
, src
, before
, true);
2603 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2605 rl78_alloc_physical_registers_op1 (rtx insn
)
2607 /* op[0] = func op[1] */
2609 /* We first try using A as the destination, then copying it
2611 if (rtx_equal_p (OP (0), OP (1)))
2614 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2618 /* If necessary, load the operands into BC and HL.
2619 Check to see if we already have OP (0) in HL
2620 and if so, swap the order. */
2622 && already_contains (HL
, XEXP (OP (0), 0)))
2624 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
2625 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
2629 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2630 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
2636 OP (0) = move_from_acc (0, insn
);
2640 /* Try copying the src to acc first, then. This is for, for
2641 example, ZERO_EXTEND or NOT. */
2642 OP (1) = move_to_acc (1, insn
);
2647 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2648 Assumes that the current insn has already been recognised and hence the
2649 constraint data has been filled in. */
2651 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
2653 const char * p
= recog_data
.constraints
[opnum
];
2655 /* No constraints means anything is accepted. */
2656 if (p
== NULL
|| *p
== 0 || *p
== ',')
2665 len
= CONSTRAINT_LEN (c
, p
);
2666 gcc_assert (len
> 0);
2674 if (lookup_constraint (p
) == constraint
)
2682 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2684 rl78_alloc_physical_registers_op2 (rtx insn
)
2692 if (rtx_equal_p (OP (0), OP (1)))
2695 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2696 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2698 else if (rtx_equal_p (OP (0), OP (2)))
2700 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2702 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2706 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2707 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2708 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2713 prev
= prev_nonnote_nondebug_insn (insn
);
2714 if (recog_data
.constraints
[1][0] == '%'
2715 && is_virtual_register (OP (1))
2716 && ! is_virtual_register (OP (2))
2717 && ! CONSTANT_P (OP (2)))
2724 /* Make a note of whether (H)L is being used. It matters
2725 because if OP (2) alsoneeds reloading, then we must take
2726 care not to corrupt HL. */
2727 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
2729 /* If HL is not currently being used and dest == op1 then there are
2730 some possible optimizations available by reloading one of the
2731 operands into HL, before trying to use the accumulator. */
2734 && rtx_equal_p (OP (0), OP (1)))
2736 /* If op0 is a Ws1 type memory address then switching the base
2737 address register to HL might allow us to perform an in-memory
2738 operation. (eg for the INCW instruction).
2740 FIXME: Adding the move into HL is costly if this optimization is not
2741 going to work, so for now, make sure that we know that the new insn will
2742 match the requirements of the addhi3_real pattern. Really we ought to
2743 generate a candidate sequence, test that, and then install it if the
2744 results are good. */
2745 if (satisfies_constraint_Ws1 (OP (0))
2746 && has_constraint (0, CONSTRAINT_Wh1
)
2747 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2749 rtx base
, index
, addend
, newbase
;
2751 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
2752 gcc_assert (index
== NULL_RTX
);
2753 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2755 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2756 if (addend
!= NULL_RTX
)
2758 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
2759 record_content (newbase
, NULL_RTX
);
2760 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
2762 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
2764 /* We do not want to fail here as this means that
2765 we have inserted useless insns into the stream. */
2769 else if (REG_P (OP (0))
2770 && satisfies_constraint_Ws1 (OP (2))
2771 && has_constraint (2, CONSTRAINT_Wh1
))
2773 rtx base
, index
, addend
, newbase
;
2775 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
2776 gcc_assert (index
== NULL_RTX
);
2777 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2779 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2780 if (addend
!= NULL_RTX
)
2782 gen_and_emit_move (HL
, base
, insn
, true);
2784 if (REGNO (OP (0)) != X_REG
)
2786 OP (1) = move_to_acc (1, insn
);
2787 OP (0) = move_from_acc (0, insn
);
2790 record_content (HL
, NULL_RTX
);
2791 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
2793 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
2795 /* We do not want to fail here as this means that
2796 we have inserted useless insns into the stream. */
2803 OP (0) = move_from_acc (0, insn
);
2805 tmp_id
= get_max_insn_count ();
2808 if (rtx_equal_p (OP (1), OP (2)))
2809 OP (2) = OP (1) = move_to_acc (1, insn
);
2811 OP (1) = move_to_acc (1, insn
);
2815 /* If we omitted the move of OP1 into the accumulator (because
2816 it was already there from a previous insn), then force the
2817 generation of the move instruction now. We know that we
2818 are about to emit a move into HL (or DE) via AX, and hence
2819 our optimization to remove the load of OP1 is no longer valid. */
2820 if (tmp_id
== get_max_insn_count ())
2821 force_into_acc (saved_op1
, insn
);
2823 /* We have to copy op2 to HL (or DE), but that involves AX, which
2824 already has a live value. Emit it before those insns. */
2827 first
= next_nonnote_nondebug_insn (prev
);
2829 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2832 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
2837 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2840 rl78_alloc_physical_registers_ro1 (rtx insn
)
2842 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2846 OP (0) = move_to_acc (0, insn
);
2851 /* Devirtualize a compare insn. */
2854 rl78_alloc_physical_registers_cmp (rtx insn
)
2858 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2861 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2862 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2864 /* HI compares have to have OP(1) in AX, but QI
2865 compares do not, so it is worth checking here. */
2868 /* For an HImode compare, OP(1) must always be in AX.
2869 But if OP(1) is a REG (and not AX), then we can avoid
2870 a reload of OP(1) if we reload OP(2) into AX and invert
2873 && REGNO (OP (1)) != AX_REG
2874 && GET_MODE (OP (1)) == HImode
2877 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
2879 OP (2) = move_to_acc (2, insn
);
2881 switch (GET_CODE (cmp
))
2886 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
2887 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
2888 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
2889 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
2902 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
2903 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
2905 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
2910 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2911 should be handled by the second alternative of the cbranchhi_real pattern. */
2912 if (rtx_equal_p (OP (1), OP (2)))
2914 OP (1) = OP (2) = BC
;
2918 tmp_id
= get_max_insn_count ();
2921 OP (1) = move_to_acc (1, insn
);
2925 /* If we omitted the move of OP1 into the accumulator (because
2926 it was already there from a previous insn), then force the
2927 generation of the move instruction now. We know that we
2928 are about to emit a move into HL via AX, and hence our
2929 optimization to remove the load of OP1 is no longer valid. */
2930 if (tmp_id
== get_max_insn_count ())
2931 force_into_acc (saved_op1
, insn
);
2933 /* We have to copy op2 to HL, but that involves the acc, which
2934 already has a live value. Emit it before those insns. */
2936 first
= next_nonnote_nondebug_insn (prev
);
2938 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2940 OP (2) = move_to_hl (2, first
);
2945 /* Like op2, but AX = A op X. */
2948 rl78_alloc_physical_registers_umul (rtx insn
)
2950 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2955 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2956 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2957 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2961 if (recog_data
.constraints
[1][0] == '%'
2962 && is_virtual_register (OP (1))
2963 && !is_virtual_register (OP (2))
2964 && !CONSTANT_P (OP (2)))
2971 OP (0) = move_from_acc (0, insn
);
2973 tmp_id
= get_max_insn_count ();
2976 OP (1) = move_to_acc (1, insn
);
2980 /* If we omitted the move of OP1 into the accumulator (because
2981 it was already there from a previous insn), then force the
2982 generation of the move instruction now. We know that we
2983 are about to emit a move into HL (or DE) via AX, and hence
2984 our optimization to remove the load of OP1 is no longer valid. */
2985 if (tmp_id
== get_max_insn_count ())
2986 force_into_acc (saved_op1
, insn
);
2988 /* We have to copy op2 to X, but that involves the acc, which
2989 already has a live value. Emit it before those insns. */
2992 first
= next_nonnote_nondebug_insn (prev
);
2994 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2996 OP (2) = move_to_x (2, first
);
3002 rl78_alloc_address_registers_macax (rtx insn
)
3005 bool replace_in_op0
= false;
3006 bool replace_in_op1
= false;
3010 /* Two different MEMs are not allowed. */
3012 for (op
= 2; op
>= 0; op
--)
3014 if (MEM_P (OP (op
)))
3016 if (op
== 0 && replace_in_op0
)
3018 if (op
== 1 && replace_in_op1
)
3024 /* If we replace a MEM, make sure that we replace it for all
3025 occurrences of the same MEM in the insn. */
3026 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3027 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3029 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3032 && (REGNO (XEXP (OP (op
), 0)) == SP_REG
3033 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3034 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3036 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3037 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3045 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3048 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3057 /* Scan all insns and devirtualize them. */
3059 rl78_alloc_physical_registers (void)
3061 /* During most of the compile, gcc is dealing with virtual
3062 registers. At this point, we need to assign physical registers
3063 to the vitual ones, and copy in/out as needed. */
3066 enum attr_valloc valloc_method
;
3068 for (insn
= get_insns (); insn
; insn
= curr
)
3072 curr
= next_nonnote_nondebug_insn (insn
);
3075 && (GET_CODE (PATTERN (insn
)) == SET
3076 || GET_CODE (PATTERN (insn
)) == CALL
)
3077 && INSN_CODE (insn
) == -1)
3079 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3081 i
= recog (PATTERN (insn
), insn
, 0);
3087 INSN_CODE (insn
) = i
;
3091 cfun
->machine
->virt_insns_ok
= 0;
3092 cfun
->machine
->real_insns_ok
= 1;
3094 clear_content_memory ();
3096 for (insn
= get_insns (); insn
; insn
= curr
)
3100 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3105 clear_content_memory ();
3111 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3113 pattern
= PATTERN (insn
);
3114 if (GET_CODE (pattern
) == PARALLEL
)
3115 pattern
= XVECEXP (pattern
, 0, 0);
3116 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3117 clear_content_memory ();
3118 if (GET_CODE (pattern
) != SET
3119 && GET_CODE (pattern
) != CALL
)
3121 if (GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3124 valloc_method
= get_attr_valloc (insn
);
3126 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3128 if (valloc_method
== VALLOC_MACAX
)
3130 record_content (AX
, NULL_RTX
);
3131 record_content (BC
, NULL_RTX
);
3132 record_content (DE
, NULL_RTX
);
3135 if (insn_ok_now (insn
))
3138 INSN_CODE (insn
) = -1;
3140 if (RTX_FRAME_RELATED_P (insn
))
3141 virt_insn_was_frame
= 1;
3143 virt_insn_was_frame
= 0;
3145 switch (valloc_method
)
3148 rl78_alloc_physical_registers_op1 (insn
);
3151 rl78_alloc_physical_registers_op2 (insn
);
3154 rl78_alloc_physical_registers_ro1 (insn
);
3157 rl78_alloc_physical_registers_cmp (insn
);
3160 rl78_alloc_physical_registers_umul (insn
);
3163 /* Macro that clobbers AX. */
3164 rl78_alloc_address_registers_macax (insn
);
3165 record_content (AX
, NULL_RTX
);
3166 record_content (BC
, NULL_RTX
);
3167 record_content (DE
, NULL_RTX
);
3171 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3172 clear_content_memory ();
3174 process_postponed_content_update ();
3177 fprintf (stderr
, "\033[0m");
3181 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3182 This function scans for uses of registers; the last use (i.e. first
3183 encounter when scanning backwards) triggers a REG_DEAD note if the
3184 reg was previously in DEAD[]. */
3186 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3195 code
= GET_CODE (s
);
3199 /* Compare registers by number. */
3204 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3205 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3206 print_rtl_single (dump_file
, s
);
3209 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3210 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3214 /* These codes have no constituent expressions
3225 /* These are kept unique for a given value. */
3232 fmt
= GET_RTX_FORMAT (code
);
3234 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3239 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3240 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3242 else if (fmt
[i
] == 'e')
3243 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3247 /* Like the previous function, but scan for SETs instead. */
3249 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3253 if (GET_CODE (d
) != REG
)
3258 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3260 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3261 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3265 /* This is a rather crude register death pass. Death status is reset
3266 at every jump or call insn. */
3268 rl78_calculate_death_notes (void)
3270 char dead
[FIRST_PSEUDO_REGISTER
];
3274 memset (dead
, 0, sizeof (dead
));
3276 for (insn
= get_last_insn ();
3278 insn
= prev_nonnote_nondebug_insn (insn
))
3282 fprintf (dump_file
, "\n--------------------------------------------------");
3283 fprintf (dump_file
, "\nDead:");
3284 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3286 fprintf (dump_file
, " %s", reg_names
[i
]);
3287 fprintf (dump_file
, "\n");
3288 print_rtl_single (dump_file
, insn
);
3291 switch (GET_CODE (insn
))
3295 switch (GET_CODE (p
))
3300 rl78_note_reg_set (dead
, d
, insn
);
3301 rl78_note_reg_uses (dead
, s
, insn
);
3305 rl78_note_reg_uses (dead
, p
, insn
);
3314 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3316 memset (dead
, 1, sizeof (dead
));
3317 /* We expect a USE just prior to this, which will mark
3318 the actual return registers. The USE will have a
3319 death note, but we aren't going to be modifying it
3324 memset (dead
, 0, sizeof (dead
));
3331 print_rtl_single (dump_file
, insn
);
3335 /* Helper function to reset the origins in RP and the age in AGE for
3338 reset_origins (int *rp
, int *age
)
3341 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3348 /* The idea behind this optimization is to look for cases where we
3349 move data from A to B to C, and instead move from A to B, and A to
3350 C. If B is a virtual register or memory, this is a big win on its
3351 own. If B turns out to be unneeded after this, it's a bigger win.
3352 For each register, we try to determine where it's value originally
3353 came from, if it's propogated purely through moves (and not
3354 computes). The ORIGINS[] array has the regno for the "origin" of
3355 the value in the [regno] it's indexed by. */
3357 rl78_propogate_register_origins (void)
3359 int origins
[FIRST_PSEUDO_REGISTER
];
3360 int age
[FIRST_PSEUDO_REGISTER
];
3362 rtx insn
, ninsn
= NULL_RTX
;
3365 reset_origins (origins
, age
);
3367 for (insn
= get_insns (); insn
; insn
= ninsn
)
3369 ninsn
= next_nonnote_nondebug_insn (insn
);
3373 fprintf (dump_file
, "\n");
3374 fprintf (dump_file
, "Origins:");
3375 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3376 if (origins
[i
] != i
)
3377 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
3378 fprintf (dump_file
, "\n");
3379 print_rtl_single (dump_file
, insn
);
3382 switch (GET_CODE (insn
))
3388 reset_origins (origins
, age
);
3395 pat
= PATTERN (insn
);
3397 if (GET_CODE (pat
) == PARALLEL
)
3399 rtx clobber
= XVECEXP (pat
, 0, 1);
3400 pat
= XVECEXP (pat
, 0, 0);
3401 if (GET_CODE (clobber
) == CLOBBER
)
3403 int cr
= REGNO (XEXP (clobber
, 0));
3404 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
3406 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
3407 for (i
= 0; i
< mb
; i
++)
3409 origins
[cr
+ i
] = cr
+ i
;
3417 if (GET_CODE (pat
) == SET
)
3419 rtx src
= SET_SRC (pat
);
3420 rtx dest
= SET_DEST (pat
);
3421 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3423 if (GET_CODE (dest
) == REG
)
3425 int dr
= REGNO (dest
);
3427 if (GET_CODE (src
) == REG
)
3429 int sr
= REGNO (src
);
3431 int best_age
, best_reg
;
3433 /* See if the copy is not needed. */
3434 for (i
= 0; i
< mb
; i
++)
3435 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3440 fprintf (dump_file
, "deleting because dest already has correct value\n");
3445 if (dr
< 8 || sr
>= 8)
3451 /* See if the copy can be made from another
3452 bank 0 register instead, instead of the
3453 virtual src register. */
3454 for (ar
= 0; ar
< 8; ar
+= mb
)
3457 for (i
= 0; i
< mb
; i
++)
3458 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3461 /* The chip has some reg-reg move limitations. */
3462 if (mb
== 1 && dr
> 3)
3467 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3469 best_age
= age
[sr
+ i
];
3477 /* FIXME: copy debug info too. */
3478 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3483 for (i
= 0; i
< mb
; i
++)
3485 origins
[dr
+ i
] = origins
[sr
+ i
];
3486 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3491 /* The destination is computed, its origin is itself. */
3493 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3494 dr
, mb
, mb
== 1 ? "" : "s");
3495 for (i
= 0; i
< mb
; i
++)
3497 origins
[dr
+ i
] = dr
+ i
;
3502 /* Any registers marked with that reg as an origin are reset. */
3503 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3504 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3511 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3512 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3515 fprintf (dump_file
, "Resetting origin of AX/BC for macro.\n");
3516 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3517 if (i
<= 3 || origins
[i
] <= 3)
3524 if (GET_CODE (src
) == ASHIFT
3525 || GET_CODE (src
) == ASHIFTRT
3526 || GET_CODE (src
) == LSHIFTRT
)
3528 rtx count
= XEXP (src
, 1);
3529 if (GET_CODE (count
) == REG
)
3531 /* Special case - our pattern clobbers the count register. */
3532 int r
= REGNO (count
);
3534 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
3535 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3536 if (i
== r
|| origins
[i
] == r
)
3548 /* Remove any SETs where the destination is unneeded. */
3550 rl78_remove_unused_sets (void)
3552 rtx insn
, ninsn
= NULL_RTX
;
3555 for (insn
= get_insns (); insn
; insn
= ninsn
)
3557 ninsn
= next_nonnote_nondebug_insn (insn
);
3559 if ((insn
= single_set (insn
)) == NULL_RTX
)
3562 dest
= SET_DEST (insn
);
3564 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
3567 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
3572 /* This is the top of the devritualization pass. */
3576 /* split2 only happens when optimizing, but we need all movSIs to be
3581 rl78_alloc_physical_registers ();
3585 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3586 print_rtl_with_bb (dump_file
, get_insns (), 0);
3589 rl78_propogate_register_origins ();
3590 rl78_calculate_death_notes ();
3594 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3595 print_rtl_with_bb (dump_file
, get_insns (), 0);
3596 fprintf (dump_file
, "\n======================================================================\n");
3599 rl78_remove_unused_sets ();
3601 /* The code after devirtualizing has changed so much that at this point
3602 we might as well just rescan everything. Note that
3603 df_rescan_all_insns is not going to help here because it does not
3604 touch the artificial uses and defs. */
3605 df_finish_pass (true);
3607 df_live_add_problem ();
3608 df_scan_alloc (NULL
);
3615 #undef TARGET_RETURN_IN_MEMORY
3616 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3619 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
3621 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
3622 return (size
== -1 || size
> 8);
3626 #undef TARGET_RTX_COSTS
3627 #define TARGET_RTX_COSTS rl78_rtx_costs
3629 static bool rl78_rtx_costs (rtx x
,
3631 int outer_code ATTRIBUTE_UNUSED
,
3632 int opno ATTRIBUTE_UNUSED
,
3634 bool speed ATTRIBUTE_UNUSED
)
3636 if (code
== IF_THEN_ELSE
)
3637 return COSTS_N_INSNS (10);
3638 if (GET_MODE (x
) == SImode
)
3644 *total
= COSTS_N_INSNS (14);
3645 else if (RL78_MUL_G13
)
3646 *total
= COSTS_N_INSNS (29);
3648 *total
= COSTS_N_INSNS (500);
3651 *total
= COSTS_N_INSNS (8);
3656 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3658 switch (INTVAL (XEXP (x
, 1)))
3660 case 0: *total
= COSTS_N_INSNS (0); break;
3661 case 1: *total
= COSTS_N_INSNS (6); break;
3662 case 2: case 3: case 4: case 5: case 6: case 7:
3663 *total
= COSTS_N_INSNS (10); break;
3664 case 8: *total
= COSTS_N_INSNS (6); break;
3665 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3666 *total
= COSTS_N_INSNS (10); break;
3667 case 16: *total
= COSTS_N_INSNS (3); break;
3668 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3669 *total
= COSTS_N_INSNS (4); break;
3670 case 24: *total
= COSTS_N_INSNS (4); break;
3671 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3672 *total
= COSTS_N_INSNS (5); break;
3676 *total
= COSTS_N_INSNS (10+4*16);
3684 #undef TARGET_UNWIND_WORD_MODE
3685 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3687 static enum machine_mode
3688 rl78_unwind_word_mode (void)
3693 struct gcc_target targetm
= TARGET_INITIALIZER
;
3695 #include "gt-rl78.h"