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
);
173 /* Redundant move elimination pass. Must be run after the basic block
174 reordering pass for the best effect. */
177 move_elim_pass (void)
179 rtx insn
, ninsn
, prev
= NULL_RTX
;
181 for (insn
= get_insns (); insn
; insn
= ninsn
)
185 ninsn
= next_nonnote_nondebug_insn (insn
);
187 if ((set
= single_set (insn
)) == NULL_RTX
)
193 /* If we have two SET insns in a row (without anything
194 between them) and the source of the second one is the
195 destination of the first one, and vice versa, then we
196 can eliminate the second SET. */
198 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
199 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
203 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
214 print_rtl_with_bb (dump_file
, get_insns (), 0);
221 const pass_data pass_data_rl78_move_elim
=
224 "move_elim", /* name */
225 OPTGROUP_NONE
, /* optinfo_flags */
227 true, /* has_execute */
228 TV_MACH_DEP
, /* tv_id */
229 0, /* properties_required */
230 0, /* properties_provided */
231 0, /* properties_destroyed */
232 0, /* todo_flags_start */
233 0, /* todo_flags_finish */
236 class pass_rl78_move_elim
: public rtl_opt_pass
239 pass_rl78_move_elim(gcc::context
*ctxt
)
240 : rtl_opt_pass(pass_data_rl78_move_elim
, ctxt
)
244 /* opt_pass methods: */
245 bool gate () { return devirt_gate (); }
246 unsigned int execute () { return move_elim_pass (); }
252 make_pass_rl78_move_elim (gcc::context
*ctxt
)
254 return new pass_rl78_move_elim (ctxt
);
257 #undef TARGET_ASM_FILE_START
258 #define TARGET_ASM_FILE_START rl78_asm_file_start
261 rl78_asm_file_start (void)
267 /* The memory used is 0xffec8 to 0xffedf; real registers are in
268 0xffee0 to 0xffee7. */
269 for (i
= 8; i
< 32; i
++)
270 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
274 for (i
= 0; i
< 8; i
++)
276 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
277 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
278 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
282 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
283 static struct register_pass_info rl78_devirt_info
=
288 PASS_POS_INSERT_BEFORE
291 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
292 static struct register_pass_info rl78_move_elim_info
=
297 PASS_POS_INSERT_AFTER
300 register_pass (& rl78_devirt_info
);
301 register_pass (& rl78_move_elim_info
);
305 #undef TARGET_OPTION_OVERRIDE
306 #define TARGET_OPTION_OVERRIDE rl78_option_override
309 rl78_option_override (void)
311 flag_omit_frame_pointer
= 1;
312 flag_no_function_cse
= 1;
313 flag_split_wide_types
= 0;
315 init_machine_status
= rl78_init_machine_status
;
321 for (i
= 24; i
< 32; i
++)
326 /* Most registers are 8 bits. Some are 16 bits because, for example,
327 gcc doesn't like dealing with $FP as a register pair. This table
328 maps register numbers to size in bytes. */
329 static const int register_sizes
[] =
331 1, 1, 1, 1, 1, 1, 1, 1,
332 1, 1, 1, 1, 1, 1, 1, 1,
333 1, 1, 1, 1, 1, 1, 2, 1,
334 1, 1, 1, 1, 1, 1, 1, 1,
338 /* Predicates used in the MD patterns. This one is true when virtual
339 insns may be matched, which typically means before (or during) the
342 rl78_virt_insns_ok (void)
345 return cfun
->machine
->virt_insns_ok
;
349 /* Predicates used in the MD patterns. This one is true when real
350 insns may be matched, which typically means after (or during) the
353 rl78_real_insns_ok (void)
356 return cfun
->machine
->real_insns_ok
;
360 /* Implements HARD_REGNO_NREGS. */
362 rl78_hard_regno_nregs (int regno
, enum machine_mode mode
)
364 int rs
= register_sizes
[regno
];
367 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
370 /* Implements HARD_REGNO_MODE_OK. */
372 rl78_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
374 int s
= GET_MODE_SIZE (mode
);
378 /* These are not to be used by gcc. */
379 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
381 /* $fp can alway sbe accessed as a 16-bit value. */
382 if (regno
== FP_REG
&& s
== 2)
386 /* Since a reg-reg move is really a reg-mem move, we must
387 enforce alignment. */
388 if (s
> 1 && (regno
% 2))
393 return (mode
== BImode
);
394 /* All other registers must be accessed in their natural sizes. */
395 if (s
== register_sizes
[regno
])
400 /* Simplify_gen_subreg() doesn't handle memory references the way we
401 need it to below, so we use this function for when we must get a
402 valid subreg in a "natural" state. */
404 rl78_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
406 if (GET_CODE (r
) == MEM
)
407 return adjust_address (r
, mode
, byte
);
409 return simplify_gen_subreg (mode
, r
, omode
, byte
);
412 /* Used by movsi. Split SImode moves into two HImode moves, using
413 appropriate patterns for the upper and lower halves of symbols. */
415 rl78_expand_movsi (rtx
*operands
)
417 rtx op00
, op02
, op10
, op12
;
419 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
420 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
421 if (GET_CODE (operands
[1]) == CONST
422 || GET_CODE (operands
[1]) == SYMBOL_REF
)
424 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
425 op10
= gen_rtx_CONST (HImode
, op10
);
426 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
427 op12
= gen_rtx_CONST (HImode
, op12
);
431 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
432 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
435 if (rtx_equal_p (operands
[0], operands
[1]))
437 else if (rtx_equal_p (op00
, op12
))
439 emit_move_insn (op02
, op12
);
440 emit_move_insn (op00
, op10
);
444 emit_move_insn (op00
, op10
);
445 emit_move_insn (op02
, op12
);
449 /* Generate code to move an SImode value. */
451 rl78_split_movsi (rtx
*operands
)
453 rtx op00
, op02
, op10
, op12
;
455 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
456 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
458 if (GET_CODE (operands
[1]) == CONST
459 || GET_CODE (operands
[1]) == SYMBOL_REF
)
461 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
462 op10
= gen_rtx_CONST (HImode
, op10
);
463 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
464 op12
= gen_rtx_CONST (HImode
, op12
);
468 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
469 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
472 if (rtx_equal_p (operands
[0], operands
[1]))
474 else if (rtx_equal_p (op00
, op12
))
490 /* Used by various two-operand expanders which cannot accept all
491 operands in the "far" namespace. Force some such operands into
492 registers so that each pattern has at most one far operand. */
494 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
499 /* FIXME: in the future, be smarter about only doing this if the
500 other operand is also far, assuming the devirtualizer can also
502 if (rl78_far_p (operands
[0]))
504 temp_reg
= operands
[0];
505 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
511 emit_insn (gen (operands
[0], operands
[1]));
513 emit_move_insn (temp_reg
, operands
[0]);
517 /* Likewise, but for three-operand expanders. */
519 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
524 /* FIXME: Likewise. */
525 if (rl78_far_p (operands
[1]))
527 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
528 emit_move_insn (temp_reg
, operands
[1]);
529 operands
[1] = temp_reg
;
532 if (rl78_far_p (operands
[0]))
534 temp_reg
= operands
[0];
535 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
541 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
543 emit_move_insn (temp_reg
, operands
[0]);
547 #undef TARGET_CAN_ELIMINATE
548 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
551 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
556 /* Returns true if the given register needs to be saved by the
559 need_to_save (unsigned int regno
)
561 if (is_interrupt_func (cfun
->decl
))
563 /* We don't know what devirt will need */
567 /* We don't need to save registers that have
568 been reserved for interrupt handlers. */
572 /* If the handler is a non-leaf function then it may call
573 non-interrupt aware routines which will happily clobber
574 any call_used registers, so we have to preserve them. */
575 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
578 /* Otherwise we only have to save a register, call_used
579 or not, if it is used by this handler. */
580 return df_regs_ever_live_p (regno
);
583 if (regno
== FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
585 if (fixed_regs
[regno
])
587 if (crtl
->calls_eh_return
)
589 if (df_regs_ever_live_p (regno
)
590 && !call_used_regs
[regno
])
595 /* We use this to wrap all emitted insns in the prologue. */
599 RTX_FRAME_RELATED_P (x
) = 1;
603 /* Compute all the frame-related fields in our machine_function
606 rl78_compute_frame_info (void)
610 cfun
->machine
->computed
= 1;
611 cfun
->machine
->framesize_regs
= 0;
612 cfun
->machine
->framesize_locals
= get_frame_size ();
613 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
615 for (i
= 0; i
< 16; i
++)
616 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
618 cfun
->machine
->need_to_push
[i
] = 1;
619 cfun
->machine
->framesize_regs
+= 2;
622 cfun
->machine
->need_to_push
[i
] = 0;
624 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
625 cfun
->machine
->framesize_locals
++;
627 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
628 + cfun
->machine
->framesize_locals
629 + cfun
->machine
->framesize_outgoing
);
632 /* Returns true if the provided function has the specified attribute. */
634 has_func_attr (const_tree decl
, const char * func_attr
)
636 if (decl
== NULL_TREE
)
637 decl
= current_function_decl
;
639 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
642 /* Returns true if the provided function has the "interrupt" attribute. */
644 is_interrupt_func (const_tree decl
)
646 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
649 /* Returns true if the provided function has the "brk_interrupt" attribute. */
651 is_brk_interrupt_func (const_tree decl
)
653 return has_func_attr (decl
, "brk_interrupt");
656 /* Check "interrupt" attributes. */
658 rl78_handle_func_attribute (tree
* node
,
661 int flags ATTRIBUTE_UNUSED
,
664 gcc_assert (DECL_P (* node
));
665 gcc_assert (args
== NULL_TREE
);
667 if (TREE_CODE (* node
) != FUNCTION_DECL
)
669 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
671 * no_add_attrs
= true;
674 /* FIXME: We ought to check that the interrupt and exception
675 handler attributes have been applied to void functions. */
679 #undef TARGET_ATTRIBUTE_TABLE
680 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
682 /* Table of RL78-specific attributes. */
683 const struct attribute_spec rl78_attribute_table
[] =
685 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
686 affects_type_identity. */
687 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
689 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
691 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute
,
693 { NULL
, 0, 0, false, false, false, NULL
, false }
698 /* Break down an address RTX into its component base/index/addend
699 portions and return TRUE if the address is of a valid form, else
702 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
708 if (GET_CODE (x
) == UNSPEC
709 && XINT (x
, 1) == UNS_ES_ADDR
)
710 x
= XVECEXP (x
, 0, 1);
712 if (GET_CODE (x
) == REG
)
718 /* We sometimes get these without the CONST wrapper */
719 if (GET_CODE (x
) == PLUS
720 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
721 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
727 if (GET_CODE (x
) == PLUS
)
732 if (GET_CODE (*base
) != REG
733 && GET_CODE (x
) == REG
)
740 if (GET_CODE (*base
) != REG
)
743 if (GET_CODE (x
) == ZERO_EXTEND
744 && GET_CODE (XEXP (x
, 0)) == REG
)
746 *index
= XEXP (x
, 0);
751 switch (GET_CODE (x
))
754 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
755 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
778 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
781 rl78_hl_b_c_addr_p (rtx op
)
785 if (GET_CODE (op
) != PLUS
)
789 if (GET_CODE (hl
) == ZERO_EXTEND
)
795 if (GET_CODE (hl
) != REG
)
797 if (GET_CODE (bc
) != ZERO_EXTEND
)
800 if (GET_CODE (bc
) != REG
)
802 if (REGNO (hl
) != HL_REG
)
804 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
810 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
812 /* Used in various constraints and predicates to match operands in the
813 "far" address space. */
820 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx(x
);
821 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
823 return MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
;
826 /* Return the appropriate mode for a named address pointer. */
827 #undef TARGET_ADDR_SPACE_POINTER_MODE
828 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
829 static enum machine_mode
830 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
834 case ADDR_SPACE_GENERIC
:
843 /* Returns TRUE for valid addresses. */
844 #undef TARGET_VALID_POINTER_MODE
845 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
847 rl78_valid_pointer_mode (enum machine_mode m
)
849 return (m
== HImode
|| m
== SImode
);
852 /* Return the appropriate mode for a named address address. */
853 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
854 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
855 static enum machine_mode
856 rl78_addr_space_address_mode (addr_space_t addrspace
)
860 case ADDR_SPACE_GENERIC
:
869 #undef TARGET_LEGITIMATE_CONSTANT_P
870 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
873 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
878 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
879 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
882 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
883 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
885 rtx base
, index
, addend
;
886 bool is_far_addr
= false;
888 if (GET_CODE (x
) == UNSPEC
889 && XINT (x
, 1) == UNS_ES_ADDR
)
891 x
= XVECEXP (x
, 0, 1);
895 if (as
== ADDR_SPACE_GENERIC
896 && (GET_MODE (x
) == SImode
|| is_far_addr
))
899 if (! characterize_address (x
, &base
, &index
, &addend
))
902 /* We can't extract the high/low portions of a PLUS address
903 involving a register during devirtualization, so make sure all
904 such __far addresses do not have addends. This forces GCC to do
905 the sum separately. */
906 if (addend
&& base
&& as
== ADDR_SPACE_FAR
)
911 int ir
= REGNO (index
);
912 int br
= REGNO (base
);
914 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
915 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
916 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
920 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
923 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
924 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
930 /* Determine if one named address space is a subset of another. */
931 #undef TARGET_ADDR_SPACE_SUBSET_P
932 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
934 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
936 gcc_assert (subset
== ADDR_SPACE_GENERIC
|| subset
== ADDR_SPACE_FAR
);
937 gcc_assert (superset
== ADDR_SPACE_GENERIC
|| superset
== ADDR_SPACE_FAR
);
939 if (subset
== superset
)
943 return (subset
== ADDR_SPACE_GENERIC
&& superset
== ADDR_SPACE_FAR
);
946 #undef TARGET_ADDR_SPACE_CONVERT
947 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
948 /* Convert from one address space to another. */
950 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
952 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
953 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
956 gcc_assert (from_as
== ADDR_SPACE_GENERIC
|| from_as
== ADDR_SPACE_FAR
);
957 gcc_assert (to_as
== ADDR_SPACE_GENERIC
|| to_as
== ADDR_SPACE_FAR
);
959 if (to_as
== ADDR_SPACE_GENERIC
&& from_as
== ADDR_SPACE_FAR
)
961 /* This is unpredictable, as we're truncating off usable address
964 result
= gen_reg_rtx (HImode
);
965 emit_move_insn (result
, simplify_subreg (HImode
, op
, SImode
, 0));
968 else if (to_as
== ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_GENERIC
)
970 /* This always works. */
971 result
= gen_reg_rtx (SImode
);
972 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
973 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
980 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
982 rl78_regno_mode_code_ok_for_base_p (int regno
, enum machine_mode mode ATTRIBUTE_UNUSED
,
983 addr_space_t address_space ATTRIBUTE_UNUSED
,
984 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
986 if (regno
<= SP_REG
&& regno
>= 16)
988 if (index_code
== REG
)
989 return (regno
== HL_REG
);
990 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
995 /* Implements MODE_CODE_BASE_REG_CLASS. */
997 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED
,
998 addr_space_t address_space ATTRIBUTE_UNUSED
,
999 int outer_code ATTRIBUTE_UNUSED
,
1000 int index_code ATTRIBUTE_UNUSED
)
1005 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1006 described in the machine_Function struct definition, above. */
1008 rl78_initial_elimination_offset (int from
, int to
)
1010 int rv
= 0; /* as if arg to arg */
1012 rl78_compute_frame_info ();
1016 case STACK_POINTER_REGNUM
:
1017 rv
+= cfun
->machine
->framesize_outgoing
;
1018 rv
+= cfun
->machine
->framesize_locals
;
1020 case FRAME_POINTER_REGNUM
:
1021 rv
+= cfun
->machine
->framesize_regs
;
1030 case FRAME_POINTER_REGNUM
:
1032 rv
-= cfun
->machine
->framesize_regs
;
1033 case ARG_POINTER_REGNUM
:
1043 rl78_is_naked_func (void)
1045 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1048 /* Expand the function prologue (from the prologue pattern). */
1050 rl78_expand_prologue (void)
1053 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1056 if (rl78_is_naked_func ())
1059 /* Always re-compute the frame info - the register usage may have changed. */
1060 rl78_compute_frame_info ();
1062 if (flag_stack_usage_info
)
1063 current_function_static_stack_size
= cfun
->machine
->framesize
;
1065 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1066 for (i
= 0; i
< 4; i
++)
1067 if (cfun
->machine
->need_to_push
[i
])
1069 /* Select Bank 0 if we are using any registers from Bank 0. */
1070 emit_insn (gen_sel_rb (GEN_INT (0)));
1074 for (i
= 0; i
< 16; i
++)
1075 if (cfun
->machine
->need_to_push
[i
])
1079 emit_move_insn (gen_rtx_REG (HImode
, 0), gen_rtx_REG (HImode
, i
*2));
1080 F (emit_insn (gen_push (gen_rtx_REG (HImode
, 0))));
1084 int need_bank
= i
/4;
1086 if (need_bank
!= rb
)
1088 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1091 F (emit_insn (gen_push (gen_rtx_REG (HImode
, i
*2))));
1096 emit_insn (gen_sel_rb (GEN_INT (0)));
1098 if (frame_pointer_needed
)
1100 F (emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1101 gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
)));
1102 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
),
1103 gen_rtx_REG (HImode
, AX_REG
)));
1106 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1109 int fs_byte
= (fs
> 254) ? 254 : fs
;
1110 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1115 /* Expand the function epilogue (from the epilogue pattern). */
1117 rl78_expand_epilogue (void)
1120 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1123 if (rl78_is_naked_func ())
1126 if (frame_pointer_needed
)
1128 emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1129 gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1130 emit_move_insn (gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
),
1131 gen_rtx_REG (HImode
, AX_REG
));
1135 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1138 int fs_byte
= (fs
> 254) ? 254 : fs
;
1140 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1145 for (i
= 15; i
>= 0; i
--)
1146 if (cfun
->machine
->need_to_push
[i
])
1150 emit_insn (gen_pop (gen_rtx_REG (HImode
, 0)));
1151 emit_move_insn (gen_rtx_REG (HImode
, i
*2), gen_rtx_REG (HImode
, 0));
1155 int need_bank
= i
/ 4;
1157 if (need_bank
!= rb
)
1159 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1162 emit_insn (gen_pop (gen_rtx_REG (HImode
, i
* 2)));
1167 emit_insn (gen_sel_rb (GEN_INT (0)));
1169 if (cfun
->machine
->trampolines_used
)
1170 emit_insn (gen_trampoline_uninit ());
1172 if (is_brk_interrupt_func (cfun
->decl
))
1173 emit_jump_insn (gen_brk_interrupt_return ());
1174 else if (is_interrupt_func (cfun
->decl
))
1175 emit_jump_insn (gen_interrupt_return ());
1177 emit_jump_insn (gen_rl78_return ());
1180 /* Likewise, for exception handlers. */
1182 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1184 /* FIXME - replace this with an indirect jump with stack adjust. */
1185 emit_jump_insn (gen_rl78_return ());
1188 #undef TARGET_ASM_FUNCTION_PROLOGUE
1189 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1191 /* We don't use this to actually emit the function prologue. We use
1192 this to insert a comment in the asm file describing the
1195 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1199 if (cfun
->machine
->framesize
== 0)
1201 fprintf (file
, "\t; start of function\n");
1203 if (cfun
->machine
->framesize_regs
)
1205 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1206 for (i
= 0; i
< 16; i
++)
1207 if (cfun
->machine
->need_to_push
[i
])
1208 fprintf (file
, " %s", word_regnames
[i
*2]);
1209 fprintf (file
, "\n");
1212 if (frame_pointer_needed
)
1213 fprintf (file
, "\t; $fp points here (r22)\n");
1215 if (cfun
->machine
->framesize_locals
)
1216 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1217 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1219 if (cfun
->machine
->framesize_outgoing
)
1220 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1221 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1224 /* Return an RTL describing where a function return value of type RET_TYPE
1227 #undef TARGET_FUNCTION_VALUE
1228 #define TARGET_FUNCTION_VALUE rl78_function_value
1231 rl78_function_value (const_tree ret_type
,
1232 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1233 bool outgoing ATTRIBUTE_UNUSED
)
1235 enum machine_mode mode
= TYPE_MODE (ret_type
);
1237 return gen_rtx_REG (mode
, 8);
1240 #undef TARGET_PROMOTE_FUNCTION_MODE
1241 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1243 static enum machine_mode
1244 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1245 enum machine_mode mode
,
1246 int *punsignedp ATTRIBUTE_UNUSED
,
1247 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1252 /* Return an RTL expression describing the register holding a function
1253 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1254 be passed on the stack. CUM describes the previous parameters to the
1255 function and NAMED is false if the parameter is part of a variable
1256 parameter list, or the last named parameter before the start of a
1257 variable parameter list. */
1259 #undef TARGET_FUNCTION_ARG
1260 #define TARGET_FUNCTION_ARG rl78_function_arg
1263 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1264 enum machine_mode mode ATTRIBUTE_UNUSED
,
1265 const_tree type ATTRIBUTE_UNUSED
,
1266 bool named ATTRIBUTE_UNUSED
)
1271 #undef TARGET_FUNCTION_ARG_ADVANCE
1272 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1275 rl78_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
, const_tree type
,
1276 bool named ATTRIBUTE_UNUSED
)
1279 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1281 rounded_size
= ((mode
== BLKmode
)
1282 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1283 if (rounded_size
& 1)
1285 (*cum
) += rounded_size
;
1288 #undef TARGET_FUNCTION_ARG_BOUNDARY
1289 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1292 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED
,
1293 const_tree type ATTRIBUTE_UNUSED
)
1298 /* Supported modifier letters:
1300 A - address of a MEM
1301 S - SADDR form of a real register
1302 v - real register corresponding to a virtual register
1303 m - minus - negative of CONST_INT value.
1304 c - inverse of a conditional (NE vs EQ for example)
1305 z - collapsed conditional
1306 s - shift count mod 8
1307 S - shift count mod 16
1308 r - reverse shift count (8-(count mod 8))
1311 h - bottom HI of an SI
1313 q - bottom QI of an HI
1315 e - third QI of an SI (i.e. where the ES register gets values from)
1316 E - fourth QI of an SI (i.e. MSB)
1320 /* Implements the bulk of rl78_print_operand, below. We do it this
1321 way because we need to test for a constant at the top level and
1322 insert the '#', but not test for it anywhere else as we recurse
1323 down into the operand. */
1325 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1329 switch (GET_CODE (op
))
1333 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1336 if (rl78_far_p (op
))
1338 fprintf (file
, "es:");
1339 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1343 op
= adjust_address (op
, HImode
, 2);
1348 op
= adjust_address (op
, HImode
, 0);
1353 op
= adjust_address (op
, QImode
, 1);
1358 op
= adjust_address (op
, QImode
, 0);
1363 op
= adjust_address (op
, QImode
, 2);
1368 op
= adjust_address (op
, QImode
, 3);
1371 if (CONSTANT_P (XEXP (op
, 0)))
1373 fprintf (file
, "!");
1374 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1376 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1377 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1379 fprintf (file
, "!");
1380 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1382 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1383 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1384 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1386 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1387 fprintf (file
, "[");
1388 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1389 fprintf (file
, "]");
1393 fprintf (file
, "[");
1394 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1395 fprintf (file
, "]");
1402 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1403 else if (letter
== 'H')
1404 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1405 else if (letter
== 'q')
1406 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1407 else if (letter
== 'e')
1408 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1409 else if (letter
== 'E')
1410 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1411 else if (letter
== 'S')
1412 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1413 else if (GET_MODE (op
) == HImode
1414 && ! (REGNO (op
) & ~0xfe))
1417 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1419 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1422 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1427 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1428 else if (letter
== 'H')
1429 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1430 else if (letter
== 'q')
1431 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1432 else if (letter
== 'h')
1433 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1434 else if (letter
== 'e')
1435 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1436 else if (letter
== 'B')
1437 fprintf (file
, "%d", exact_log2 (INTVAL (op
)));
1438 else if (letter
== 'E')
1439 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1440 else if (letter
== 'm')
1441 fprintf (file
, "%ld", - INTVAL (op
));
1442 else if (letter
== 's')
1443 fprintf (file
, "%ld", INTVAL (op
) % 8);
1444 else if (letter
== 'S')
1445 fprintf (file
, "%ld", INTVAL (op
) % 16);
1446 else if (letter
== 'r')
1447 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1448 else if (letter
== 'C')
1449 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1451 fprintf (file
, "%ld", INTVAL (op
));
1455 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1460 int bits
= INTVAL (XEXP (op
, 1));
1461 int ofs
= INTVAL (XEXP (op
, 2));
1462 if (bits
== 16 && ofs
== 0)
1463 fprintf (file
, "%%lo16(");
1464 else if (bits
== 16 && ofs
== 16)
1465 fprintf (file
, "%%hi16(");
1466 else if (bits
== 8 && ofs
== 16)
1467 fprintf (file
, "%%hi8(");
1470 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1471 fprintf (file
, ")");
1476 if (GET_CODE (XEXP (op
, 0)) == REG
)
1477 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1479 print_rtl (file
, op
);
1486 fprintf (file
, "%%hi16(");
1492 fprintf (file
, "%%lo16(");
1498 fprintf (file
, "%%hi8(");
1502 if (letter
== 'q' || letter
== 'Q')
1503 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1505 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1507 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1508 fprintf (file
, "+");
1509 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1513 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1514 fprintf (file
, "+");
1515 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1518 fprintf (file
, ")");
1525 fprintf (file
, "%%hi16(");
1531 fprintf (file
, "%%lo16(");
1537 fprintf (file
, "%%hi8(");
1541 if (letter
== 'q' || letter
== 'Q')
1542 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1544 output_addr_const (file
, op
);
1546 fprintf (file
, ")");
1551 output_asm_label (op
);
1556 fprintf (file
, "#comparison eliminated");
1558 fprintf (file
, letter
== 'c' ? "nc" : "c");
1562 fprintf (file
, "br");
1564 fprintf (file
, letter
== 'c' ? "h" : "nh");
1568 fprintf (file
, "br");
1570 fprintf (file
, letter
== 'c' ? "c" : "nc");
1574 fprintf (file
, "#comparison eliminated");
1576 fprintf (file
, letter
== 'c' ? "nh" : "h");
1580 fprintf (file
, "br");
1582 fprintf (file
, letter
== 'c' ? "nz" : "z");
1586 fprintf (file
, "#comparison eliminated");
1588 fprintf (file
, letter
== 'c' ? "z" : "nz");
1591 /* Note: these assume appropriate adjustments were made so that
1592 unsigned comparisons, which is all this chip has, will
1596 fprintf (file
, "#comparison eliminated");
1598 fprintf (file
, letter
== 'c' ? "nc" : "c");
1602 fprintf (file
, "br");
1604 fprintf (file
, letter
== 'c' ? "h" : "nh");
1608 fprintf (file
, "br");
1610 fprintf (file
, letter
== 'c' ? "c" : "nc");
1614 fprintf (file
, "#comparison eliminated");
1616 fprintf (file
, letter
== 'c' ? "nh" : "h");
1620 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1625 #undef TARGET_PRINT_OPERAND
1626 #define TARGET_PRINT_OPERAND rl78_print_operand
1629 rl78_print_operand (FILE * file
, rtx op
, int letter
)
1631 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
1632 fprintf (file
, "#");
1633 rl78_print_operand_1 (file
, op
, letter
);
1636 #undef TARGET_TRAMPOLINE_INIT
1637 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1639 /* Note that the RL78's addressing makes it very difficult to do
1640 trampolines on the stack. So, libgcc has a small pool of
1641 trampolines from which one is allocated to this task. */
1643 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
1645 rtx mov_addr
, thunk_addr
;
1646 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
1648 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
1649 thunk_addr
= gen_reg_rtx (HImode
);
1651 function
= force_reg (HImode
, function
);
1652 static_chain
= force_reg (HImode
, static_chain
);
1654 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
1655 emit_move_insn (mov_addr
, thunk_addr
);
1657 cfun
->machine
->trampolines_used
= 1;
1660 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1661 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1664 rl78_trampoline_adjust_address (rtx m_tramp
)
1666 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
1670 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1671 the "normal" compares, specifically, it only has unsigned compares,
1672 so we must synthesize the missing ones. */
1674 rl78_expand_compare (rtx
*operands
)
1676 if (GET_CODE (operands
[2]) == MEM
)
1677 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
1682 /* Define this to 1 if you are debugging the peephole optimizers. */
1683 #define DEBUG_PEEP 0
1685 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1686 The default "word" size is a byte so we can effectively use all the
1687 registers, but we want to do 16-bit moves whenever possible. This
1688 function determines when such a move is an option. */
1690 rl78_peep_movhi_p (rtx
*operands
)
1695 /* (set (op0) (op1))
1696 (set (op2) (op3)) */
1698 if (! rl78_virt_insns_ok ())
1702 fprintf (stderr
, "\033[33m");
1703 debug_rtx (operands
[0]);
1704 debug_rtx (operands
[1]);
1705 debug_rtx (operands
[2]);
1706 debug_rtx (operands
[3]);
1707 fprintf (stderr
, "\033[0m");
1710 /* You can move a constant to memory as QImode, but not HImode. */
1711 if (GET_CODE (operands
[0]) == MEM
1712 && GET_CODE (operands
[1]) != REG
)
1715 fprintf (stderr
, "no peep: move constant to memory\n");
1720 if (rtx_equal_p (operands
[0], operands
[3]))
1723 fprintf (stderr
, "no peep: overlapping\n");
1728 for (i
= 0; i
< 2; i
++)
1730 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
1733 fprintf (stderr
, "no peep: different codes\n");
1737 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
1740 fprintf (stderr
, "no peep: different modes\n");
1745 switch (GET_CODE (operands
[i
]))
1749 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
1750 || GET_MODE (operands
[i
]) != QImode
)
1753 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
1754 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
1759 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
1762 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
1772 if (GET_MODE (operands
[i
]) != QImode
)
1774 if (MEM_ALIGN (operands
[i
]) < 16)
1776 a
= XEXP (operands
[i
], 0);
1777 if (GET_CODE (a
) == CONST
)
1779 if (GET_CODE (a
) == PLUS
)
1781 if (GET_CODE (a
) == CONST_INT
1785 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
1786 debug_rtx (operands
[i
]);
1790 m
= adjust_address (operands
[i
], QImode
, 1);
1791 if (! rtx_equal_p (m
, operands
[i
+2]))
1794 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
1796 debug_rtx (operands
[i
+2]);
1804 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
1810 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
1815 /* Likewise, when a peephole is activated, this function helps compute
1816 the new operands. */
1818 rl78_setup_peep_movhi (rtx
*operands
)
1822 for (i
= 0; i
< 2; i
++)
1824 switch (GET_CODE (operands
[i
]))
1827 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
1831 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char)INTVAL (operands
[i
+2])) * 256);
1835 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
1845 How Devirtualization works in the RL78 GCC port
1849 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1850 bytes of register space, in four banks, memory-mapped. One bank is
1851 the "selected" bank and holds the registers used for primary
1852 operations. Since the registers are memory mapped, often you can
1853 still refer to the unselected banks via memory accesses.
1857 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1858 and refers to the other banks via their memory addresses, although
1859 they're treated as regular registers internally. These "virtual"
1860 registers are R8 through R23 (bank3 is reserved for asm-based
1861 interrupt handlers).
1863 There are four machine description files:
1865 rl78.md - common register-independent patterns and definitions
1866 rl78-expand.md - expanders
1867 rl78-virt.md - patterns that match BEFORE devirtualization
1868 rl78-real.md - patterns that match AFTER devirtualization
1870 At least through register allocation and reload, gcc is told that it
1871 can do pretty much anything - but may only use the virtual registers.
1872 GCC cannot properly create the varying addressing modes that the RL78
1873 supports in an efficient way.
1875 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1876 uses the "valloc" attribute in rl78-virt.md for determining the rules
1877 by which it will replace virtual registers with real registers (or
1878 not) and how to make up addressing modes. For example, insns tagged
1879 with "ro1" have a single read-only parameter, which may need to be
1880 moved from memory/constant/vreg to a suitable real register. As part
1881 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1882 patterns and enabling the rl78-real.md patterns. The new patterns'
1883 constraints are used to determine the real registers used. NOTE:
1884 patterns in rl78-virt.md essentially ignore the constrains and rely on
1885 predicates, where the rl78-real.md ones essentially ignore the
1886 predicates and rely on the constraints.
1888 The devirtualization pass is scheduled via the pass manager (despite
1889 being called "rl78_reorg") so it can be scheduled prior to var-track
1890 (the idea is to let gdb know about the new registers). Ideally, it
1891 would be scheduled right after pro/epilogue generation, so the
1892 post-reload optimizers could operate on the real registers, but when I
1893 tried that there were some issues building the target libraries.
1895 During devirtualization, a simple register move optimizer is run. It
1896 would be better to run a full CSE/propogation pass on it through, or
1897 re-run regmove, but that has not yet been attempted.
1900 #define DEBUG_ALLOC 0
1902 #define OP(x) (*recog_data.operand_loc[x])
1904 /* This array is used to hold knowledge about the contents of the
1905 real registers (A ... H), the memory-based registers (r8 ... r31)
1906 and the first NUM_STACK_LOCS words on the stack. We use this to
1907 avoid generating redundant move instructions.
1909 A value in the range 0 .. 31 indicates register A .. r31.
1910 A value in the range 32 .. 63 indicates stack slot (value - 32).
1911 A value of NOT_KNOWN indicates that the contents of that location
1914 #define NUM_STACK_LOCS 32
1915 #define NOT_KNOWN 127
1917 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
1919 static unsigned char saved_update_index
= NOT_KNOWN
;
1920 static unsigned char saved_update_value
;
1921 static enum machine_mode saved_update_mode
;
1925 clear_content_memory (void)
1927 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
1929 fprintf (dump_file
, " clear content memory\n");
1930 saved_update_index
= NOT_KNOWN
;
1933 /* Convert LOC into an index into the content_memory array.
1934 If LOC cannot be converted, return NOT_KNOWN. */
1936 static unsigned char
1937 get_content_index (rtx loc
)
1939 enum machine_mode mode
;
1941 if (loc
== NULL_RTX
)
1946 if (REGNO (loc
) < 32)
1951 mode
= GET_MODE (loc
);
1953 if (! rl78_stack_based_mem (loc
, mode
))
1956 loc
= XEXP (loc
, 0);
1959 /* loc = MEM (SP) */
1962 /* loc = MEM (PLUS (SP, INT)). */
1963 loc
= XEXP (loc
, 1);
1965 if (INTVAL (loc
) < NUM_STACK_LOCS
)
1966 return 32 + INTVAL (loc
);
1971 /* Return a string describing content INDEX in mode MODE.
1972 WARNING: Can return a pointer to a static buffer. */
1974 get_content_name (unsigned char index
, enum machine_mode mode
)
1976 static char buffer
[128];
1978 if (index
== NOT_KNOWN
)
1982 sprintf (buffer
, "stack slot %d", index
- 32);
1983 else if (mode
== HImode
)
1984 sprintf (buffer
, "%s%s",
1985 reg_names
[index
+ 1], reg_names
[index
]);
1987 return reg_names
[index
];
1995 display_content_memory (FILE * file
)
1999 fprintf (file
, " Known memory contents:\n");
2001 for (i
= 0; i
< sizeof content_memory
; i
++)
2002 if (content_memory
[i
] != NOT_KNOWN
)
2004 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
2005 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2011 update_content (unsigned char index
, unsigned char val
, enum machine_mode mode
)
2015 gcc_assert (index
< sizeof content_memory
);
2017 content_memory
[index
] = val
;
2018 if (val
!= NOT_KNOWN
)
2019 content_memory
[val
] = index
;
2021 /* Make the entry in dump_file *before* VAL is increased below. */
2024 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2025 if (val
== NOT_KNOWN
)
2026 fprintf (dump_file
, "Unknown\n");
2028 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2033 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2035 content_memory
[index
+ 1] = val
;
2036 if (val
!= NOT_KNOWN
)
2038 content_memory
[val
] = index
+ 1;
2043 /* Any other places that had INDEX recorded as their contents are now invalid. */
2044 for (i
= 0; i
< sizeof content_memory
; i
++)
2047 || (val
!= NOT_KNOWN
&& i
== val
))
2054 if (content_memory
[i
] == index
2055 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2057 content_memory
[i
] = NOT_KNOWN
;
2060 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2063 content_memory
[++ i
] = NOT_KNOWN
;
2068 /* Record that LOC contains VALUE.
2069 For HImode locations record that LOC+1 contains VALUE+1.
2070 If LOC is not a register or stack slot, do nothing.
2071 If VALUE is not a register or stack slot, clear the recorded content. */
2074 record_content (rtx loc
, rtx value
)
2076 enum machine_mode mode
;
2077 unsigned char index
;
2080 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2083 val
= get_content_index (value
);
2085 mode
= GET_MODE (loc
);
2092 /* This should not happen when optimizing. */
2094 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2095 get_content_name (val
, mode
));
2102 update_content (index
, val
, mode
);
2105 /* Returns TRUE if LOC already contains a copy of VALUE. */
2108 already_contains (rtx loc
, rtx value
)
2110 unsigned char index
;
2113 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2116 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2119 if (content_memory
[index
] != val
)
2122 if (GET_MODE (loc
) == HImode
)
2123 return content_memory
[index
+ 1] == val
+ 1;
2129 rl78_es_addr (rtx addr
)
2131 if (GET_CODE (addr
) == MEM
)
2132 addr
= XEXP (addr
, 0);
2133 if (GET_CODE (addr
) != UNSPEC
)
2135 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2141 rl78_es_base (rtx addr
)
2143 if (GET_CODE (addr
) == MEM
)
2144 addr
= XEXP (addr
, 0);
2145 addr
= XVECEXP (addr
, 0, 1);
2146 if (GET_CODE (addr
) == CONST
2147 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2148 addr
= XEXP (XEXP (addr
, 0), 0);
2149 /* Mode doesn't matter here. */
2150 return gen_rtx_MEM (HImode
, addr
);
2153 /* Rescans an insn to see if it's recognized again. This is done
2154 carefully to ensure that all the constraint information is accurate
2155 for the newly matched insn. */
2157 insn_ok_now (rtx insn
)
2159 rtx pattern
= PATTERN (insn
);
2162 INSN_CODE (insn
) = -1;
2164 if (recog (pattern
, insn
, 0) > -1)
2166 extract_insn (insn
);
2167 if (constrain_operands (1))
2170 fprintf (stderr
, "\033[32m");
2172 fprintf (stderr
, "\033[0m");
2174 if (SET_P (pattern
))
2175 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2177 /* We need to detect far addresses that haven't been
2178 converted to es/lo16 format. */
2179 for (i
=0; i
<recog_data
.n_operands
; i
++)
2180 if (GET_CODE (OP (i
)) == MEM
2181 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2182 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2190 /* We need to re-recog the insn with virtual registers to get
2192 cfun
->machine
->virt_insns_ok
= 1;
2193 if (recog (pattern
, insn
, 0) > -1)
2195 extract_insn (insn
);
2196 if (constrain_operands (0))
2198 cfun
->machine
->virt_insns_ok
= 0;
2204 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2211 fprintf (stderr
, "\033[31m");
2213 fprintf (stderr
, "\033[0m");
2219 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2220 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2221 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2222 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2223 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2225 #define FAILED gcc_unreachable ()
2226 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2227 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2230 /* Registers into which we move the contents of virtual registers. */
2231 #define X gen_rtx_REG (QImode, X_REG)
2232 #define A gen_rtx_REG (QImode, A_REG)
2233 #define C gen_rtx_REG (QImode, C_REG)
2234 #define B gen_rtx_REG (QImode, B_REG)
2235 #define E gen_rtx_REG (QImode, E_REG)
2236 #define D gen_rtx_REG (QImode, D_REG)
2237 #define L gen_rtx_REG (QImode, L_REG)
2238 #define H gen_rtx_REG (QImode, H_REG)
2240 #define AX gen_rtx_REG (HImode, AX_REG)
2241 #define BC gen_rtx_REG (HImode, BC_REG)
2242 #define DE gen_rtx_REG (HImode, DE_REG)
2243 #define HL gen_rtx_REG (HImode, HL_REG)
2245 /* Returns TRUE if R is a virtual register. */
2247 is_virtual_register (rtx r
)
2249 return (GET_CODE (r
) == REG
2254 /* In all these alloc routines, we expect the following: the insn
2255 pattern is unshared, the insn was previously recognized and failed
2256 due to predicates or constraints, and the operand data is in
2259 static int virt_insn_was_frame
;
2261 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2264 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2267 fprintf (stderr
, "\033[36m%d: ", line
);
2269 fprintf (stderr
, "\033[0m");
2271 /*SCHED_GROUP_P (r) = 1;*/
2272 if (virt_insn_was_frame
)
2273 RTX_FRAME_RELATED_P (r
) = 1;
2277 #define EM(x) EM2 (__LINE__, x)
2279 /* Return a suitable RTX for the low half of a __far address. */
2281 rl78_lo16 (rtx addr
)
2285 if (GET_CODE (addr
) == SYMBOL_REF
2286 || GET_CODE (addr
) == CONST
)
2288 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2289 r
= gen_rtx_CONST (HImode
, r
);
2292 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2294 r
= gen_es_addr (r
);
2299 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2303 if (GET_CODE (addr
) == SYMBOL_REF
2304 || GET_CODE (addr
) == CONST
)
2306 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2307 r
= gen_rtx_CONST (QImode
, r
);
2310 return rl78_subreg (QImode
, addr
, SImode
, 2);
2314 add_postponed_content_update (rtx to
, rtx value
)
2316 unsigned char index
;
2318 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2321 gcc_assert (saved_update_index
== NOT_KNOWN
);
2322 saved_update_index
= index
;
2323 saved_update_value
= get_content_index (value
);
2324 saved_update_mode
= GET_MODE (to
);
2328 process_postponed_content_update (void)
2330 if (saved_update_index
!= NOT_KNOWN
)
2332 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2333 saved_update_index
= NOT_KNOWN
;
2337 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2338 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2339 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2340 BEFORE is true, FROM otherwise. */
2342 gen_and_emit_move (rtx to
, rtx from
, rtx where
, bool before
)
2344 enum machine_mode mode
= GET_MODE (to
);
2346 if (optimize
&& before
&& already_contains (to
, from
))
2349 display_content_memory (stderr
);
2353 fprintf (dump_file
, " Omit move of %s into ",
2354 get_content_name (get_content_index (from
), mode
));
2355 fprintf (dump_file
, "%s as it already contains this value\n",
2356 get_content_name (get_content_index (to
), mode
));
2361 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2365 if (where
== NULL_RTX
)
2368 emit_insn_before (move
, where
);
2371 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2373 /* If necessary move REG_EH_REGION notes forward.
2374 cf. compiling gcc.dg/pr44545.c. */
2375 if (note
!= NULL_RTX
)
2377 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2378 remove_note (where
, note
);
2381 emit_insn_after (move
, where
);
2385 record_content (to
, from
);
2387 add_postponed_content_update (to
, from
);
2390 return before
? to
: from
;
2393 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2394 copy it into NEWBASE and return the updated MEM. Otherwise just
2395 return M. Any needed insns are emitted before BEFORE. */
2397 transcode_memory_rtx (rtx m
, rtx newbase
, rtx before
)
2399 rtx base
, index
, addendr
;
2406 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2409 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2412 fprintf (stderr
, "setting ES:\n");
2415 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2416 emit_insn_before (EM (gen_movqi_es (A
)), before
);
2417 record_content (A
, NULL_RTX
);
2419 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2420 MEM_COPY_ATTRIBUTES (new_m
, m
);
2425 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2426 gcc_assert (index
== NULL_RTX
);
2429 fprintf (stderr
, "\033[33m"); debug_rtx (m
); fprintf (stderr
, "\033[0m");
2432 if (base
== NULL_RTX
)
2435 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2436 addend
= INTVAL (addendr
);
2438 gcc_assert (REG_P (base
));
2439 gcc_assert (REG_P (newbase
));
2441 if (REGNO (base
) == SP_REG
)
2443 if (addend
>= 0 && addend
<= 255)
2447 /* BASE should be a virtual register. We copy it to NEWBASE. If
2448 the addend is out of range for DE/HL, we use AX to compute the full
2452 || (addend
> 255 && REGNO (newbase
) != 2)
2453 || (addendr
&& GET_CODE (addendr
) != CONST_INT
))
2458 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2459 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2460 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2461 record_content (AX
, NULL_RTX
);
2462 record_content (newbase
, NULL_RTX
);
2469 base
= gen_and_emit_move (newbase
, base
, before
, true);
2474 record_content (base
, NULL_RTX
);
2475 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2479 fprintf (stderr
, "\033[33m");
2483 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2485 m
= change_address (m
, GET_MODE (m
), base
);
2488 fprintf (stderr
, "\033[0m");
2493 /* Copy SRC to accumulator (A or AX), placing any generated insns
2494 before BEFORE. Returns accumulator RTX. */
2496 move_to_acc (int opno
, rtx before
)
2498 rtx src
= OP (opno
);
2499 enum machine_mode mode
= GET_MODE (src
);
2501 if (REG_P (src
) && REGNO (src
) < 2)
2504 if (mode
== VOIDmode
)
2505 mode
= recog_data
.operand_mode
[opno
];
2507 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2511 force_into_acc (rtx src
, rtx before
)
2513 enum machine_mode mode
= GET_MODE (src
);
2516 if (REG_P (src
) && REGNO (src
) < 2)
2519 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2523 emit_insn_before (move
, before
);
2524 record_content (AX
, NULL_RTX
);
2527 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2528 after AFTER. Returns accumulator RTX. */
2530 move_from_acc (unsigned int opno
, rtx after
)
2532 rtx dest
= OP (opno
);
2533 enum machine_mode mode
= GET_MODE (dest
);
2535 if (REG_P (dest
) && REGNO (dest
) < 2)
2538 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2541 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2542 before BEFORE. Returns reg RTX. */
2544 move_acc_to_reg (rtx acc
, int regno
, rtx before
)
2546 enum machine_mode mode
= GET_MODE (acc
);
2549 reg
= gen_rtx_REG (mode
, regno
);
2551 return gen_and_emit_move (reg
, acc
, before
, true);
2554 /* Copy SRC to X, placing any generated insns before BEFORE.
2557 move_to_x (int opno
, rtx before
)
2559 rtx src
= OP (opno
);
2560 enum machine_mode mode
= GET_MODE (src
);
2563 if (mode
== VOIDmode
)
2564 mode
= recog_data
.operand_mode
[opno
];
2565 reg
= (mode
== QImode
) ? X
: AX
;
2567 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2569 OP (opno
) = move_to_acc (opno
, before
);
2570 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
2574 return gen_and_emit_move (reg
, src
, before
, true);
2577 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2578 Returns H/HL RTX. */
2580 move_to_hl (int opno
, rtx before
)
2582 rtx src
= OP (opno
);
2583 enum machine_mode mode
= GET_MODE (src
);
2586 if (mode
== VOIDmode
)
2587 mode
= recog_data
.operand_mode
[opno
];
2588 reg
= (mode
== QImode
) ? L
: HL
;
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
), L_REG
, before
);
2597 return gen_and_emit_move (reg
, src
, before
, true);
2600 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2601 Returns E/DE RTX. */
2603 move_to_de (int opno
, rtx before
)
2605 rtx src
= OP (opno
);
2606 enum machine_mode mode
= GET_MODE (src
);
2609 if (mode
== VOIDmode
)
2610 mode
= recog_data
.operand_mode
[opno
];
2612 reg
= (mode
== QImode
) ? E
: DE
;
2614 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2616 OP (opno
) = move_to_acc (opno
, before
);
2617 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
2621 gen_and_emit_move (reg
, src
, before
, true);
2627 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2629 rl78_alloc_physical_registers_op1 (rtx insn
)
2631 /* op[0] = func op[1] */
2633 /* We first try using A as the destination, then copying it
2635 if (rtx_equal_p (OP (0), OP (1)))
2638 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2642 /* If necessary, load the operands into BC and HL.
2643 Check to see if we already have OP (0) in HL
2644 and if so, swap the order. */
2646 && already_contains (HL
, XEXP (OP (0), 0)))
2648 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
2649 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
2653 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2654 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
2660 OP (0) = move_from_acc (0, insn
);
2664 /* Try copying the src to acc first, then. This is for, for
2665 example, ZERO_EXTEND or NOT. */
2666 OP (1) = move_to_acc (1, insn
);
2671 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2672 Assumes that the current insn has already been recognised and hence the
2673 constraint data has been filled in. */
2675 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
2677 const char * p
= recog_data
.constraints
[opnum
];
2679 /* No constraints means anything is accepted. */
2680 if (p
== NULL
|| *p
== 0 || *p
== ',')
2689 len
= CONSTRAINT_LEN (c
, p
);
2690 gcc_assert (len
> 0);
2698 if (lookup_constraint (p
) == constraint
)
2706 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2708 rl78_alloc_physical_registers_op2 (rtx insn
)
2716 if (rtx_equal_p (OP (0), OP (1)))
2719 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2720 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2722 else if (rtx_equal_p (OP (0), OP (2)))
2724 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2726 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2730 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2731 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2732 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2737 prev
= prev_nonnote_nondebug_insn (insn
);
2738 if (recog_data
.constraints
[1][0] == '%'
2739 && is_virtual_register (OP (1))
2740 && ! is_virtual_register (OP (2))
2741 && ! CONSTANT_P (OP (2)))
2748 /* Make a note of whether (H)L is being used. It matters
2749 because if OP (2) alsoneeds reloading, then we must take
2750 care not to corrupt HL. */
2751 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
2753 /* If HL is not currently being used and dest == op1 then there are
2754 some possible optimizations available by reloading one of the
2755 operands into HL, before trying to use the accumulator. */
2758 && rtx_equal_p (OP (0), OP (1)))
2760 /* If op0 is a Ws1 type memory address then switching the base
2761 address register to HL might allow us to perform an in-memory
2762 operation. (eg for the INCW instruction).
2764 FIXME: Adding the move into HL is costly if this optimization is not
2765 going to work, so for now, make sure that we know that the new insn will
2766 match the requirements of the addhi3_real pattern. Really we ought to
2767 generate a candidate sequence, test that, and then install it if the
2768 results are good. */
2769 if (satisfies_constraint_Ws1 (OP (0))
2770 && has_constraint (0, CONSTRAINT_Wh1
)
2771 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2773 rtx base
, index
, addend
, newbase
;
2775 characterize_address (XEXP (OP (0), 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 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
2783 record_content (newbase
, NULL_RTX
);
2784 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
2786 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
2788 /* We do not want to fail here as this means that
2789 we have inserted useless insns into the stream. */
2793 else if (REG_P (OP (0))
2794 && satisfies_constraint_Ws1 (OP (2))
2795 && has_constraint (2, CONSTRAINT_Wh1
))
2797 rtx base
, index
, addend
, newbase
;
2799 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
2800 gcc_assert (index
== NULL_RTX
);
2801 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2803 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2804 if (addend
!= NULL_RTX
)
2806 gen_and_emit_move (HL
, base
, insn
, true);
2808 if (REGNO (OP (0)) != X_REG
)
2810 OP (1) = move_to_acc (1, insn
);
2811 OP (0) = move_from_acc (0, insn
);
2814 record_content (HL
, NULL_RTX
);
2815 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
2817 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
2819 /* We do not want to fail here as this means that
2820 we have inserted useless insns into the stream. */
2826 OP (0) = move_from_acc (0, insn
);
2828 tmp_id
= get_max_insn_count ();
2831 if (rtx_equal_p (OP (1), OP (2)))
2832 OP (2) = OP (1) = move_to_acc (1, insn
);
2834 OP (1) = move_to_acc (1, insn
);
2838 /* If we omitted the move of OP1 into the accumulator (because
2839 it was already there from a previous insn), then force the
2840 generation of the move instruction now. We know that we
2841 are about to emit a move into HL (or DE) via AX, and hence
2842 our optimization to remove the load of OP1 is no longer valid. */
2843 if (tmp_id
== get_max_insn_count ())
2844 force_into_acc (saved_op1
, insn
);
2846 /* We have to copy op2 to HL (or DE), but that involves AX, which
2847 already has a live value. Emit it before those insns. */
2850 first
= next_nonnote_nondebug_insn (prev
);
2852 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2855 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
2860 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2862 rl78_alloc_physical_registers_ro1 (rtx insn
)
2864 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2868 OP (0) = move_to_acc (0, insn
);
2873 /* Devirtualize a compare insn. */
2875 rl78_alloc_physical_registers_cmp (rtx insn
)
2879 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2882 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2883 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2885 /* HI compares have to have OP (1) in AX, but QI
2886 compares do not, so it is worth checking here. */
2889 /* For an HImode compare, OP (1) must always be in AX.
2890 But if OP (1) is a REG (and not AX), then we can avoid
2891 a reload of OP (1) if we reload OP (2) into AX and invert
2894 && REGNO (OP (1)) != AX_REG
2895 && GET_MODE (OP (1)) == HImode
2898 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
2900 OP (2) = move_to_acc (2, insn
);
2902 switch (GET_CODE (cmp
))
2907 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
2908 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
2909 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
2910 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
2923 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
2924 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
2926 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
2931 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2932 should be handled by the second alternative of the cbranchhi_real pattern. */
2933 if (rtx_equal_p (OP (1), OP (2)))
2935 OP (1) = OP (2) = BC
;
2939 tmp_id
= get_max_insn_count ();
2942 OP (1) = move_to_acc (1, insn
);
2946 /* If we omitted the move of OP1 into the accumulator (because
2947 it was already there from a previous insn), then force the
2948 generation of the move instruction now. We know that we
2949 are about to emit a move into HL via AX, and hence our
2950 optimization to remove the load of OP1 is no longer valid. */
2951 if (tmp_id
== get_max_insn_count ())
2952 force_into_acc (saved_op1
, insn
);
2954 /* We have to copy op2 to HL, but that involves the acc, which
2955 already has a live value. Emit it before those insns. */
2957 first
= next_nonnote_nondebug_insn (prev
);
2959 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2961 OP (2) = move_to_hl (2, first
);
2966 /* Like op2, but AX = A op X. */
2968 rl78_alloc_physical_registers_umul (rtx insn
)
2970 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2975 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2976 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2977 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2981 if (recog_data
.constraints
[1][0] == '%'
2982 && is_virtual_register (OP (1))
2983 && !is_virtual_register (OP (2))
2984 && !CONSTANT_P (OP (2)))
2991 OP (0) = move_from_acc (0, insn
);
2993 tmp_id
= get_max_insn_count ();
2996 OP (1) = move_to_acc (1, insn
);
3000 /* If we omitted the move of OP1 into the accumulator (because
3001 it was already there from a previous insn), then force the
3002 generation of the move instruction now. We know that we
3003 are about to emit a move into HL (or DE) via AX, and hence
3004 our optimization to remove the load of OP1 is no longer valid. */
3005 if (tmp_id
== get_max_insn_count ())
3006 force_into_acc (saved_op1
, insn
);
3008 /* We have to copy op2 to X, but that involves the acc, which
3009 already has a live value. Emit it before those insns. */
3012 first
= next_nonnote_nondebug_insn (prev
);
3014 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3016 OP (2) = move_to_x (2, first
);
3022 rl78_alloc_address_registers_macax (rtx insn
)
3025 bool replace_in_op0
= false;
3026 bool replace_in_op1
= false;
3030 /* Two different MEMs are not allowed. */
3032 for (op
= 2; op
>= 0; op
--)
3034 if (MEM_P (OP (op
)))
3036 if (op
== 0 && replace_in_op0
)
3038 if (op
== 1 && replace_in_op1
)
3044 /* If we replace a MEM, make sure that we replace it for all
3045 occurrences of the same MEM in the insn. */
3046 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3047 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3049 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3052 && (REGNO (XEXP (OP (op
), 0)) == SP_REG
3053 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3054 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3056 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3057 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3065 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3068 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3078 /* Scan all insns and devirtualize them. */
3080 rl78_alloc_physical_registers (void)
3082 /* During most of the compile, gcc is dealing with virtual
3083 registers. At this point, we need to assign physical registers
3084 to the vitual ones, and copy in/out as needed. */
3087 enum attr_valloc valloc_method
;
3089 for (insn
= get_insns (); insn
; insn
= curr
)
3093 curr
= next_nonnote_nondebug_insn (insn
);
3096 && (GET_CODE (PATTERN (insn
)) == SET
3097 || GET_CODE (PATTERN (insn
)) == CALL
)
3098 && INSN_CODE (insn
) == -1)
3100 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3102 i
= recog (PATTERN (insn
), insn
, 0);
3108 INSN_CODE (insn
) = i
;
3112 cfun
->machine
->virt_insns_ok
= 0;
3113 cfun
->machine
->real_insns_ok
= 1;
3115 clear_content_memory ();
3117 for (insn
= get_insns (); insn
; insn
= curr
)
3121 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3126 clear_content_memory ();
3132 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3134 pattern
= PATTERN (insn
);
3135 if (GET_CODE (pattern
) == PARALLEL
)
3136 pattern
= XVECEXP (pattern
, 0, 0);
3137 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3138 clear_content_memory ();
3139 if (GET_CODE (pattern
) != SET
3140 && GET_CODE (pattern
) != CALL
)
3142 if (GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3145 valloc_method
= get_attr_valloc (insn
);
3147 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3149 if (valloc_method
== VALLOC_MACAX
)
3151 record_content (AX
, NULL_RTX
);
3152 record_content (BC
, NULL_RTX
);
3153 record_content (DE
, NULL_RTX
);
3156 if (insn_ok_now (insn
))
3159 INSN_CODE (insn
) = -1;
3161 if (RTX_FRAME_RELATED_P (insn
))
3162 virt_insn_was_frame
= 1;
3164 virt_insn_was_frame
= 0;
3166 switch (valloc_method
)
3169 rl78_alloc_physical_registers_op1 (insn
);
3172 rl78_alloc_physical_registers_op2 (insn
);
3175 rl78_alloc_physical_registers_ro1 (insn
);
3178 rl78_alloc_physical_registers_cmp (insn
);
3181 rl78_alloc_physical_registers_umul (insn
);
3184 /* Macro that clobbers AX. */
3185 rl78_alloc_address_registers_macax (insn
);
3186 record_content (AX
, NULL_RTX
);
3187 record_content (BC
, NULL_RTX
);
3188 record_content (DE
, NULL_RTX
);
3192 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3193 clear_content_memory ();
3195 process_postponed_content_update ();
3199 fprintf (stderr
, "\033[0m");
3203 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3204 This function scans for uses of registers; the last use (i.e. first
3205 encounter when scanning backwards) triggers a REG_DEAD note if the
3206 reg was previously in DEAD[]. */
3208 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3217 code
= GET_CODE (s
);
3221 /* Compare registers by number. */
3226 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3227 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3228 print_rtl_single (dump_file
, s
);
3231 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3232 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3236 /* These codes have no constituent expressions
3247 /* These are kept unique for a given value. */
3254 fmt
= GET_RTX_FORMAT (code
);
3256 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3261 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3262 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3264 else if (fmt
[i
] == 'e')
3265 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3269 /* Like the previous function, but scan for SETs instead. */
3271 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3275 if (GET_CODE (d
) != REG
)
3280 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3282 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3283 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3287 /* This is a rather crude register death pass. Death status is reset
3288 at every jump or call insn. */
3290 rl78_calculate_death_notes (void)
3292 char dead
[FIRST_PSEUDO_REGISTER
];
3296 memset (dead
, 0, sizeof (dead
));
3298 for (insn
= get_last_insn ();
3300 insn
= prev_nonnote_nondebug_insn (insn
))
3304 fprintf (dump_file
, "\n--------------------------------------------------");
3305 fprintf (dump_file
, "\nDead:");
3306 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3308 fprintf (dump_file
, " %s", reg_names
[i
]);
3309 fprintf (dump_file
, "\n");
3310 print_rtl_single (dump_file
, insn
);
3313 switch (GET_CODE (insn
))
3317 switch (GET_CODE (p
))
3322 rl78_note_reg_set (dead
, d
, insn
);
3323 rl78_note_reg_uses (dead
, s
, insn
);
3327 rl78_note_reg_uses (dead
, p
, insn
);
3336 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3338 memset (dead
, 1, sizeof (dead
));
3339 /* We expect a USE just prior to this, which will mark
3340 the actual return registers. The USE will have a
3341 death note, but we aren't going to be modifying it
3346 memset (dead
, 0, sizeof (dead
));
3353 print_rtl_single (dump_file
, insn
);
3357 /* Helper function to reset the origins in RP and the age in AGE for
3360 reset_origins (int *rp
, int *age
)
3363 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3370 /* The idea behind this optimization is to look for cases where we
3371 move data from A to B to C, and instead move from A to B, and A to
3372 C. If B is a virtual register or memory, this is a big win on its
3373 own. If B turns out to be unneeded after this, it's a bigger win.
3374 For each register, we try to determine where it's value originally
3375 came from, if it's propogated purely through moves (and not
3376 computes). The ORIGINS[] array has the regno for the "origin" of
3377 the value in the [regno] it's indexed by. */
3379 rl78_propogate_register_origins (void)
3381 int origins
[FIRST_PSEUDO_REGISTER
];
3382 int age
[FIRST_PSEUDO_REGISTER
];
3384 rtx insn
, ninsn
= NULL_RTX
;
3387 reset_origins (origins
, age
);
3389 for (insn
= get_insns (); insn
; insn
= ninsn
)
3391 ninsn
= next_nonnote_nondebug_insn (insn
);
3395 fprintf (dump_file
, "\n");
3396 fprintf (dump_file
, "Origins:");
3397 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3398 if (origins
[i
] != i
)
3399 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
3400 fprintf (dump_file
, "\n");
3401 print_rtl_single (dump_file
, insn
);
3404 switch (GET_CODE (insn
))
3410 reset_origins (origins
, age
);
3417 pat
= PATTERN (insn
);
3419 if (GET_CODE (pat
) == PARALLEL
)
3421 rtx clobber
= XVECEXP (pat
, 0, 1);
3422 pat
= XVECEXP (pat
, 0, 0);
3423 if (GET_CODE (clobber
) == CLOBBER
)
3425 int cr
= REGNO (XEXP (clobber
, 0));
3426 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
3428 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
3429 for (i
= 0; i
< mb
; i
++)
3431 origins
[cr
+ i
] = cr
+ i
;
3439 if (GET_CODE (pat
) == SET
)
3441 rtx src
= SET_SRC (pat
);
3442 rtx dest
= SET_DEST (pat
);
3443 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3445 if (GET_CODE (dest
) == REG
)
3447 int dr
= REGNO (dest
);
3449 if (GET_CODE (src
) == REG
)
3451 int sr
= REGNO (src
);
3453 int best_age
, best_reg
;
3455 /* See if the copy is not needed. */
3456 for (i
= 0; i
< mb
; i
++)
3457 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3462 fprintf (dump_file
, "deleting because dest already has correct value\n");
3467 if (dr
< 8 || sr
>= 8)
3473 /* See if the copy can be made from another
3474 bank 0 register instead, instead of the
3475 virtual src register. */
3476 for (ar
= 0; ar
< 8; ar
+= mb
)
3479 for (i
= 0; i
< mb
; i
++)
3480 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3483 /* The chip has some reg-reg move limitations. */
3484 if (mb
== 1 && dr
> 3)
3489 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3491 best_age
= age
[sr
+ i
];
3499 /* FIXME: copy debug info too. */
3500 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3505 for (i
= 0; i
< mb
; i
++)
3507 origins
[dr
+ i
] = origins
[sr
+ i
];
3508 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3513 /* The destination is computed, its origin is itself. */
3515 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3516 dr
, mb
, mb
== 1 ? "" : "s");
3517 for (i
= 0; i
< mb
; i
++)
3519 origins
[dr
+ i
] = dr
+ i
;
3524 /* Any registers marked with that reg as an origin are reset. */
3525 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3526 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3533 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3534 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3537 fprintf (dump_file
, "Resetting origin of AX/BC for macro.\n");
3538 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3539 if (i
<= 3 || origins
[i
] <= 3)
3546 if (GET_CODE (src
) == ASHIFT
3547 || GET_CODE (src
) == ASHIFTRT
3548 || GET_CODE (src
) == LSHIFTRT
)
3550 rtx count
= XEXP (src
, 1);
3551 if (GET_CODE (count
) == REG
)
3553 /* Special case - our pattern clobbers the count register. */
3554 int r
= REGNO (count
);
3556 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
3557 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3558 if (i
== r
|| origins
[i
] == r
)
3566 else if (GET_CODE (pat
) == CLOBBER
)
3568 if (REG_P (XEXP (pat
, 0)))
3570 unsigned int reg
= REGNO (XEXP (pat
, 0));
3580 /* Remove any SETs where the destination is unneeded. */
3582 rl78_remove_unused_sets (void)
3584 rtx insn
, ninsn
= NULL_RTX
;
3587 for (insn
= get_insns (); insn
; insn
= ninsn
)
3589 ninsn
= next_nonnote_nondebug_insn (insn
);
3591 if ((insn
= single_set (insn
)) == NULL_RTX
)
3594 dest
= SET_DEST (insn
);
3596 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
3599 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
3604 /* This is the top of the devritualization pass. */
3608 /* split2 only happens when optimizing, but we need all movSIs to be
3613 rl78_alloc_physical_registers ();
3617 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3618 print_rtl_with_bb (dump_file
, get_insns (), 0);
3621 rl78_propogate_register_origins ();
3622 rl78_calculate_death_notes ();
3626 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3627 print_rtl_with_bb (dump_file
, get_insns (), 0);
3628 fprintf (dump_file
, "\n======================================================================\n");
3631 rl78_remove_unused_sets ();
3633 /* The code after devirtualizing has changed so much that at this point
3634 we might as well just rescan everything. Note that
3635 df_rescan_all_insns is not going to help here because it does not
3636 touch the artificial uses and defs. */
3637 df_finish_pass (true);
3639 df_live_add_problem ();
3640 df_scan_alloc (NULL
);
3647 #undef TARGET_RETURN_IN_MEMORY
3648 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3651 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
3653 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
3654 return (size
== -1 || size
> 8);
3658 #undef TARGET_RTX_COSTS
3659 #define TARGET_RTX_COSTS rl78_rtx_costs
3661 static bool rl78_rtx_costs (rtx x
,
3663 int outer_code ATTRIBUTE_UNUSED
,
3664 int opno ATTRIBUTE_UNUSED
,
3666 bool speed ATTRIBUTE_UNUSED
)
3668 if (code
== IF_THEN_ELSE
)
3669 return COSTS_N_INSNS (10);
3670 if (GET_MODE (x
) == SImode
)
3676 *total
= COSTS_N_INSNS (14);
3677 else if (RL78_MUL_G13
)
3678 *total
= COSTS_N_INSNS (29);
3680 *total
= COSTS_N_INSNS (500);
3683 *total
= COSTS_N_INSNS (8);
3688 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3690 switch (INTVAL (XEXP (x
, 1)))
3692 case 0: *total
= COSTS_N_INSNS (0); break;
3693 case 1: *total
= COSTS_N_INSNS (6); break;
3694 case 2: case 3: case 4: case 5: case 6: case 7:
3695 *total
= COSTS_N_INSNS (10); break;
3696 case 8: *total
= COSTS_N_INSNS (6); break;
3697 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3698 *total
= COSTS_N_INSNS (10); break;
3699 case 16: *total
= COSTS_N_INSNS (3); break;
3700 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3701 *total
= COSTS_N_INSNS (4); break;
3702 case 24: *total
= COSTS_N_INSNS (4); break;
3703 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3704 *total
= COSTS_N_INSNS (5); break;
3708 *total
= COSTS_N_INSNS (10+4*16);
3716 #undef TARGET_UNWIND_WORD_MODE
3717 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3719 static enum machine_mode
3720 rl78_unwind_word_mode (void)
3726 struct gcc_target targetm
= TARGET_INITIALIZER
;
3728 #include "gt-rl78.h"