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
);
278 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
279 static struct register_pass_info rl78_devirt_info
=
284 PASS_POS_INSERT_BEFORE
287 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
288 static struct register_pass_info rl78_move_elim_info
=
293 PASS_POS_INSERT_AFTER
296 register_pass (& rl78_devirt_info
);
297 register_pass (& rl78_move_elim_info
);
301 #undef TARGET_OPTION_OVERRIDE
302 #define TARGET_OPTION_OVERRIDE rl78_option_override
305 rl78_option_override (void)
307 flag_omit_frame_pointer
= 1;
308 flag_no_function_cse
= 1;
309 flag_split_wide_types
= 0;
311 init_machine_status
= rl78_init_machine_status
;
314 /* Most registers are 8 bits. Some are 16 bits because, for example,
315 gcc doesn't like dealing with $FP as a register pair. This table
316 maps register numbers to size in bytes. */
317 static const int register_sizes
[] =
319 1, 1, 1, 1, 1, 1, 1, 1,
320 1, 1, 1, 1, 1, 1, 1, 1,
321 1, 1, 1, 1, 1, 1, 2, 1,
322 1, 1, 1, 1, 1, 1, 1, 1,
326 /* Predicates used in the MD patterns. This one is true when virtual
327 insns may be matched, which typically means before (or during) the
330 rl78_virt_insns_ok (void)
333 return cfun
->machine
->virt_insns_ok
;
337 /* Predicates used in the MD patterns. This one is true when real
338 insns may be matched, which typically means after (or during) the
341 rl78_real_insns_ok (void)
344 return cfun
->machine
->real_insns_ok
;
348 /* Implements HARD_REGNO_NREGS. */
350 rl78_hard_regno_nregs (int regno
, enum machine_mode mode
)
352 int rs
= register_sizes
[regno
];
355 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
358 /* Implements HARD_REGNO_MODE_OK. */
360 rl78_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
362 int s
= GET_MODE_SIZE (mode
);
366 /* These are not to be used by gcc. */
367 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
369 /* $fp can alway sbe accessed as a 16-bit value. */
370 if (regno
== FP_REG
&& s
== 2)
374 /* Since a reg-reg move is really a reg-mem move, we must
375 enforce alignment. */
376 if (s
> 1 && (regno
% 2))
381 return (mode
== BImode
);
382 /* All other registers must be accessed in their natural sizes. */
383 if (s
== register_sizes
[regno
])
388 /* Simplify_gen_subreg() doesn't handle memory references the way we
389 need it to below, so we use this function for when we must get a
390 valid subreg in a "natural" state. */
392 rl78_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
394 if (GET_CODE (r
) == MEM
)
395 return adjust_address (r
, mode
, byte
);
397 return simplify_gen_subreg (mode
, r
, omode
, byte
);
400 /* Used by movsi. Split SImode moves into two HImode moves, using
401 appropriate patterns for the upper and lower halves of symbols. */
403 rl78_expand_movsi (rtx
*operands
)
405 rtx op00
, op02
, op10
, op12
;
407 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
408 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
409 if (GET_CODE (operands
[1]) == CONST
410 || GET_CODE (operands
[1]) == SYMBOL_REF
)
412 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
413 op10
= gen_rtx_CONST (HImode
, op10
);
414 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
415 op12
= gen_rtx_CONST (HImode
, op12
);
419 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
420 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
423 if (rtx_equal_p (operands
[0], operands
[1]))
425 else if (rtx_equal_p (op00
, op12
))
427 emit_move_insn (op02
, op12
);
428 emit_move_insn (op00
, op10
);
432 emit_move_insn (op00
, op10
);
433 emit_move_insn (op02
, op12
);
438 rl78_split_movsi (rtx
*operands
)
440 rtx op00
, op02
, op10
, op12
;
442 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
443 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
444 if (GET_CODE (operands
[1]) == CONST
445 || GET_CODE (operands
[1]) == SYMBOL_REF
)
447 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
448 op10
= gen_rtx_CONST (HImode
, op10
);
449 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
450 op12
= gen_rtx_CONST (HImode
, op12
);
454 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
455 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
458 if (rtx_equal_p (operands
[0], operands
[1]))
460 else if (rtx_equal_p (op00
, op12
))
477 /* Used by various two-operand expanders which cannot accept all
478 operands in the "far" namespace. Force some such operands into
479 registers so that each pattern has at most one far operand. */
481 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
486 /* FIXME: in the future, be smarter about only doing this if the
487 other operand is also far, assuming the devirtualizer can also
489 if (rl78_far_p (operands
[0]))
491 temp_reg
= operands
[0];
492 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
498 emit_insn (gen (operands
[0], operands
[1]));
500 emit_move_insn (temp_reg
, operands
[0]);
504 /* Likewise, but for three-operand expanders. */
506 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
511 /* FIXME: Likewise. */
512 if (rl78_far_p (operands
[1]))
514 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
515 emit_move_insn (temp_reg
, operands
[1]);
516 operands
[1] = temp_reg
;
519 if (rl78_far_p (operands
[0]))
521 temp_reg
= operands
[0];
522 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
528 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
530 emit_move_insn (temp_reg
, operands
[0]);
534 #undef TARGET_CAN_ELIMINATE
535 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
538 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
543 /* Returns true if the given register needs to be saved by the
546 need_to_save (unsigned int regno
)
548 if (is_interrupt_func (cfun
->decl
))
550 /* We don't need to save registers that have
551 been reserved for interrupt handlers. */
555 /* If the handler is a non-leaf function then it may call
556 non-interrupt aware routines which will happily clobber
557 any call_used registers, so we have to preserve them. */
558 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
561 /* Otherwise we only have to save a register, call_used
562 or not, if it is used by this handler. */
563 return df_regs_ever_live_p (regno
);
566 if (regno
== FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
568 if (fixed_regs
[regno
])
570 if (crtl
->calls_eh_return
)
572 if (df_regs_ever_live_p (regno
)
573 && !call_used_regs
[regno
])
578 /* We use this to wrap all emitted insns in the prologue. */
582 RTX_FRAME_RELATED_P (x
) = 1;
586 /* Compute all the frame-related fields in our machine_function
589 rl78_compute_frame_info (void)
593 cfun
->machine
->computed
= 1;
594 cfun
->machine
->framesize_regs
= 0;
595 cfun
->machine
->framesize_locals
= get_frame_size ();
596 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
598 for (i
= 0; i
< 16; i
++)
599 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
601 cfun
->machine
->need_to_push
[i
] = 1;
602 cfun
->machine
->framesize_regs
+= 2;
605 cfun
->machine
->need_to_push
[i
] = 0;
607 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
608 cfun
->machine
->framesize_locals
++;
610 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
611 + cfun
->machine
->framesize_locals
612 + cfun
->machine
->framesize_outgoing
);
615 /* Returns true if the provided function has the specified attribute. */
617 has_func_attr (const_tree decl
, const char * func_attr
)
619 if (decl
== NULL_TREE
)
620 decl
= current_function_decl
;
622 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
625 /* Returns true if the provided function has the "interrupt" attribute. */
627 is_interrupt_func (const_tree decl
)
629 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
632 /* Returns true if the provided function has the "brk_interrupt" attribute. */
634 is_brk_interrupt_func (const_tree decl
)
636 return has_func_attr (decl
, "brk_interrupt");
639 /* Check "interrupt" attributes. */
641 rl78_handle_func_attribute (tree
* node
,
644 int flags ATTRIBUTE_UNUSED
,
647 gcc_assert (DECL_P (* node
));
648 gcc_assert (args
== NULL_TREE
);
650 if (TREE_CODE (* node
) != FUNCTION_DECL
)
652 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
654 * no_add_attrs
= true;
657 /* FIXME: We ought to check that the interrupt and exception
658 handler attributes have been applied to void functions. */
662 #undef TARGET_ATTRIBUTE_TABLE
663 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
665 /* Table of RL78-specific attributes. */
666 const struct attribute_spec rl78_attribute_table
[] =
668 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
669 affects_type_identity. */
670 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
672 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
674 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute
,
676 { NULL
, 0, 0, false, false, false, NULL
, false }
681 /* Break down an address RTX into its component base/index/addend
682 portions and return TRUE if the address is of a valid form, else
685 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
691 if (GET_CODE (x
) == REG
)
697 /* We sometimes get these without the CONST wrapper */
698 if (GET_CODE (x
) == PLUS
699 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
700 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
706 if (GET_CODE (x
) == PLUS
)
711 if (GET_CODE (*base
) != REG
712 && GET_CODE (x
) == REG
)
719 if (GET_CODE (*base
) != REG
)
722 if (GET_CODE (x
) == ZERO_EXTEND
723 && GET_CODE (XEXP (x
, 0)) == REG
)
725 *index
= XEXP (x
, 0);
730 switch (GET_CODE (x
))
733 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
734 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
757 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
760 rl78_hl_b_c_addr_p (rtx op
)
764 if (GET_CODE (op
) != PLUS
)
768 if (GET_CODE (hl
) == ZERO_EXTEND
)
774 if (GET_CODE (hl
) != REG
)
776 if (GET_CODE (bc
) != ZERO_EXTEND
)
779 if (GET_CODE (bc
) != REG
)
781 if (REGNO (hl
) != HL_REG
)
783 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
789 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
791 /* Used in various constraints and predicates to match operands in the
792 "far" address space. */
799 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx(x
);
800 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
802 return MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
;
805 /* Return the appropriate mode for a named address pointer. */
806 #undef TARGET_ADDR_SPACE_POINTER_MODE
807 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
808 static enum machine_mode
809 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
813 case ADDR_SPACE_GENERIC
:
822 /* Returns TRUE for valid addresses. */
823 #undef TARGET_VALID_POINTER_MODE
824 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
826 rl78_valid_pointer_mode (enum machine_mode m
)
828 return (m
== HImode
|| m
== SImode
);
831 /* Return the appropriate mode for a named address address. */
832 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
833 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
834 static enum machine_mode
835 rl78_addr_space_address_mode (addr_space_t addrspace
)
839 case ADDR_SPACE_GENERIC
:
848 #undef TARGET_LEGITIMATE_CONSTANT_P
849 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
852 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
857 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
858 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
861 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
862 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
864 rtx base
, index
, addend
;
866 if (GET_CODE (x
) == UNSPEC
867 && XINT (x
, 1) == UNS_ES_ADDR
)
868 x
= XVECEXP (x
, 0, 1);
870 if (as
== ADDR_SPACE_GENERIC
871 && GET_MODE (x
) == SImode
)
874 if (! characterize_address (x
, &base
, &index
, &addend
))
877 /* We can't extract the high/low portions of a PLUS address
878 involving a register during devirtualization, so make sure all
879 such __far addresses do not have addends. This forces GCC to do
880 the sum separately. */
881 if (addend
&& base
&& as
== ADDR_SPACE_FAR
)
886 int ir
= REGNO (index
);
887 int br
= REGNO (base
);
889 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
890 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
891 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
895 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
898 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
899 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
905 /* Determine if one named address space is a subset of another. */
906 #undef TARGET_ADDR_SPACE_SUBSET_P
907 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
909 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
911 gcc_assert (subset
== ADDR_SPACE_GENERIC
|| subset
== ADDR_SPACE_FAR
);
912 gcc_assert (superset
== ADDR_SPACE_GENERIC
|| superset
== ADDR_SPACE_FAR
);
914 if (subset
== superset
)
918 return (subset
== ADDR_SPACE_GENERIC
&& superset
== ADDR_SPACE_FAR
);
921 #undef TARGET_ADDR_SPACE_CONVERT
922 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
923 /* Convert from one address space to another. */
925 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
927 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
928 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
931 gcc_assert (from_as
== ADDR_SPACE_GENERIC
|| from_as
== ADDR_SPACE_FAR
);
932 gcc_assert (to_as
== ADDR_SPACE_GENERIC
|| to_as
== ADDR_SPACE_FAR
);
934 if (to_as
== ADDR_SPACE_GENERIC
&& from_as
== ADDR_SPACE_FAR
)
936 /* This is unpredictable, as we're truncating off usable address
939 result
= gen_reg_rtx (HImode
);
940 emit_move_insn (result
, simplify_subreg (HImode
, op
, SImode
, 0));
943 else if (to_as
== ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_GENERIC
)
945 /* This always works. */
946 result
= gen_reg_rtx (SImode
);
947 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
948 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
955 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
957 rl78_regno_mode_code_ok_for_base_p (int regno
, enum machine_mode mode ATTRIBUTE_UNUSED
,
958 addr_space_t address_space ATTRIBUTE_UNUSED
,
959 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
961 if (regno
<= SP_REG
&& regno
>= 16)
963 if (index_code
== REG
)
964 return (regno
== HL_REG
);
965 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
970 /* Implements MODE_CODE_BASE_REG_CLASS. */
972 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED
,
973 addr_space_t address_space ATTRIBUTE_UNUSED
,
974 int outer_code ATTRIBUTE_UNUSED
,
975 int index_code ATTRIBUTE_UNUSED
)
980 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
981 described in the machine_Function struct definition, above. */
983 rl78_initial_elimination_offset (int from
, int to
)
985 int rv
= 0; /* as if arg to arg */
987 rl78_compute_frame_info ();
991 case STACK_POINTER_REGNUM
:
992 rv
+= cfun
->machine
->framesize_outgoing
;
993 rv
+= cfun
->machine
->framesize_locals
;
995 case FRAME_POINTER_REGNUM
:
996 rv
+= cfun
->machine
->framesize_regs
;
1005 case FRAME_POINTER_REGNUM
:
1007 rv
-= cfun
->machine
->framesize_regs
;
1008 case ARG_POINTER_REGNUM
:
1018 rl78_is_naked_func (void)
1020 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1023 /* Expand the function prologue (from the prologue pattern). */
1025 rl78_expand_prologue (void)
1028 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1031 if (rl78_is_naked_func ())
1034 /* Always re-compute the frame info - the register usage may have changed. */
1035 rl78_compute_frame_info ();
1037 if (flag_stack_usage_info
)
1038 current_function_static_stack_size
= cfun
->machine
->framesize
;
1040 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1041 for (i
= 0; i
< 4; i
++)
1042 if (cfun
->machine
->need_to_push
[i
])
1044 /* Select Bank 0 if we are using any registers from Bank 0. */
1045 emit_insn (gen_sel_rb (GEN_INT (0)));
1049 for (i
= 0; i
< 16; i
++)
1050 if (cfun
->machine
->need_to_push
[i
])
1054 emit_move_insn (gen_rtx_REG (HImode
, 0), gen_rtx_REG (HImode
, i
*2));
1055 F (emit_insn (gen_push (gen_rtx_REG (HImode
, 0))));
1058 int need_bank
= i
/4;
1059 if (need_bank
!= rb
)
1061 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1064 F (emit_insn (gen_push (gen_rtx_REG (HImode
, i
*2))));
1068 emit_insn (gen_sel_rb (GEN_INT (0)));
1070 if (frame_pointer_needed
)
1072 F (emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1073 gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
)));
1074 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
),
1075 gen_rtx_REG (HImode
, AX_REG
)));
1078 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1081 int fs_byte
= (fs
> 254) ? 254 : fs
;
1082 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1087 /* Expand the function epilogue (from the epilogue pattern). */
1089 rl78_expand_epilogue (void)
1092 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1095 if (rl78_is_naked_func ())
1098 if (frame_pointer_needed
)
1100 emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1101 gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1102 emit_move_insn (gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
),
1103 gen_rtx_REG (HImode
, AX_REG
));
1107 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1110 int fs_byte
= (fs
> 254) ? 254 : fs
;
1112 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1117 for (i
= 15; i
>= 0; i
--)
1118 if (cfun
->machine
->need_to_push
[i
])
1122 emit_insn (gen_pop (gen_rtx_REG (HImode
, 0)));
1123 emit_move_insn (gen_rtx_REG (HImode
, i
*2), gen_rtx_REG (HImode
, 0));
1127 int need_bank
= i
/ 4;
1129 if (need_bank
!= rb
)
1131 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1134 emit_insn (gen_pop (gen_rtx_REG (HImode
, i
* 2)));
1139 emit_insn (gen_sel_rb (GEN_INT (0)));
1141 if (cfun
->machine
->trampolines_used
)
1142 emit_insn (gen_trampoline_uninit ());
1144 if (is_brk_interrupt_func (cfun
->decl
))
1145 emit_jump_insn (gen_brk_interrupt_return ());
1146 else if (is_interrupt_func (cfun
->decl
))
1147 emit_jump_insn (gen_interrupt_return ());
1149 emit_jump_insn (gen_rl78_return ());
1152 /* Likewise, for exception handlers. */
1154 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1156 /* FIXME - replace this with an indirect jump with stack adjust. */
1157 emit_jump_insn (gen_rl78_return ());
1160 #undef TARGET_ASM_FUNCTION_PROLOGUE
1161 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1163 /* We don't use this to actually emit the function prologue. We use
1164 this to insert a comment in the asm file describing the
1167 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1171 if (cfun
->machine
->framesize
== 0)
1173 fprintf (file
, "\t; start of function\n");
1175 if (cfun
->machine
->framesize_regs
)
1177 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1178 for (i
= 0; i
< 16; i
++)
1179 if (cfun
->machine
->need_to_push
[i
])
1180 fprintf (file
, " %s", word_regnames
[i
*2]);
1181 fprintf (file
, "\n");
1184 if (frame_pointer_needed
)
1185 fprintf (file
, "\t; $fp points here (r22)\n");
1187 if (cfun
->machine
->framesize_locals
)
1188 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1189 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1191 if (cfun
->machine
->framesize_outgoing
)
1192 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1193 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1196 /* Return an RTL describing where a function return value of type RET_TYPE
1199 #undef TARGET_FUNCTION_VALUE
1200 #define TARGET_FUNCTION_VALUE rl78_function_value
1203 rl78_function_value (const_tree ret_type
,
1204 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1205 bool outgoing ATTRIBUTE_UNUSED
)
1207 enum machine_mode mode
= TYPE_MODE (ret_type
);
1209 return gen_rtx_REG (mode
, 8);
1212 #undef TARGET_PROMOTE_FUNCTION_MODE
1213 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1215 static enum machine_mode
1216 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1217 enum machine_mode mode
,
1218 int *punsignedp ATTRIBUTE_UNUSED
,
1219 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1224 /* Return an RTL expression describing the register holding a function
1225 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1226 be passed on the stack. CUM describes the previous parameters to the
1227 function and NAMED is false if the parameter is part of a variable
1228 parameter list, or the last named parameter before the start of a
1229 variable parameter list. */
1231 #undef TARGET_FUNCTION_ARG
1232 #define TARGET_FUNCTION_ARG rl78_function_arg
1235 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1236 enum machine_mode mode ATTRIBUTE_UNUSED
,
1237 const_tree type ATTRIBUTE_UNUSED
,
1238 bool named ATTRIBUTE_UNUSED
)
1243 #undef TARGET_FUNCTION_ARG_ADVANCE
1244 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1247 rl78_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
, const_tree type
,
1248 bool named ATTRIBUTE_UNUSED
)
1251 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1253 rounded_size
= ((mode
== BLKmode
)
1254 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1255 if (rounded_size
& 1)
1257 (*cum
) += rounded_size
;
1260 #undef TARGET_FUNCTION_ARG_BOUNDARY
1261 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1264 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED
,
1265 const_tree type ATTRIBUTE_UNUSED
)
1270 /* Supported modifier letters:
1272 A - address of a MEM
1273 S - SADDR form of a real register
1274 v - real register corresponding to a virtual register
1275 m - minus - negative of CONST_INT value.
1276 c - inverse of a conditional (NE vs EQ for example)
1277 z - collapsed conditional
1278 s - shift count mod 8
1279 S - shift count mod 16
1280 r - reverse shift count (8-(count mod 8))
1282 h - bottom HI of an SI
1284 q - bottom QI of an HI
1286 e - third QI of an SI (i.e. where the ES register gets values from)
1287 E - fourth QI of an SI (i.e. MSB)
1291 /* Implements the bulk of rl78_print_operand, below. We do it this
1292 way because we need to test for a constant at the top level and
1293 insert the '#', but not test for it anywhere else as we recurse
1294 down into the operand. */
1296 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1300 switch (GET_CODE (op
))
1304 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1307 if (rl78_far_p (op
))
1309 fprintf (file
, "es:");
1310 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1314 op
= adjust_address (op
, HImode
, 2);
1319 op
= adjust_address (op
, HImode
, 0);
1324 op
= adjust_address (op
, QImode
, 1);
1329 op
= adjust_address (op
, QImode
, 0);
1334 op
= adjust_address (op
, QImode
, 2);
1339 op
= adjust_address (op
, QImode
, 3);
1342 if (CONSTANT_P (XEXP (op
, 0)))
1344 fprintf (file
, "!");
1345 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1347 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1348 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1350 fprintf (file
, "!");
1351 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1353 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1354 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1355 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1357 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1358 fprintf (file
, "[");
1359 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1360 fprintf (file
, "]");
1364 fprintf (file
, "[");
1365 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1366 fprintf (file
, "]");
1373 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1374 else if (letter
== 'H')
1375 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1376 else if (letter
== 'q')
1377 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1378 else if (letter
== 'e')
1379 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1380 else if (letter
== 'E')
1381 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1382 else if (letter
== 'S')
1383 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1384 else if (GET_MODE (op
) == HImode
1385 && ! (REGNO (op
) & ~0xfe))
1388 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1390 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1393 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1398 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1399 else if (letter
== 'H')
1400 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1401 else if (letter
== 'q')
1402 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1403 else if (letter
== 'h')
1404 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1405 else if (letter
== 'e')
1406 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1407 else if (letter
== 'E')
1408 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1409 else if (letter
== 'm')
1410 fprintf (file
, "%ld", - INTVAL (op
));
1411 else if (letter
== 's')
1412 fprintf (file
, "%ld", INTVAL (op
) % 8);
1413 else if (letter
== 'S')
1414 fprintf (file
, "%ld", INTVAL (op
) % 16);
1415 else if (letter
== 'r')
1416 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1417 else if (letter
== 'C')
1418 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1420 fprintf (file
, "%ld", INTVAL (op
));
1424 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1429 int bits
= INTVAL (XEXP (op
, 1));
1430 int ofs
= INTVAL (XEXP (op
, 2));
1431 if (bits
== 16 && ofs
== 0)
1432 fprintf (file
, "%%lo16(");
1433 else if (bits
== 16 && ofs
== 16)
1434 fprintf (file
, "%%hi16(");
1435 else if (bits
== 8 && ofs
== 16)
1436 fprintf (file
, "%%hi8(");
1439 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1440 fprintf (file
, ")");
1445 if (GET_CODE (XEXP (op
, 0)) == REG
)
1446 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1448 print_rtl (file
, op
);
1455 fprintf (file
, "%%hi16(");
1461 fprintf (file
, "%%lo16(");
1467 fprintf (file
, "%%hi8(");
1471 if (letter
== 'q' || letter
== 'Q')
1472 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1474 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1476 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1477 fprintf (file
, "+");
1478 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1482 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1483 fprintf (file
, "+");
1484 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1487 fprintf (file
, ")");
1494 fprintf (file
, "%%hi16(");
1500 fprintf (file
, "%%lo16(");
1506 fprintf (file
, "%%hi8(");
1510 if (letter
== 'q' || letter
== 'Q')
1511 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1513 output_addr_const (file
, op
);
1515 fprintf (file
, ")");
1520 output_asm_label (op
);
1525 fprintf (file
, "#comparison eliminated");
1527 fprintf (file
, letter
== 'c' ? "nc" : "c");
1531 fprintf (file
, "br");
1533 fprintf (file
, letter
== 'c' ? "h" : "nh");
1537 fprintf (file
, "br");
1539 fprintf (file
, letter
== 'c' ? "c" : "nc");
1543 fprintf (file
, "#comparison eliminated");
1545 fprintf (file
, letter
== 'c' ? "nh" : "h");
1549 fprintf (file
, "br");
1551 fprintf (file
, letter
== 'c' ? "nz" : "z");
1555 fprintf (file
, "#comparison eliminated");
1557 fprintf (file
, letter
== 'c' ? "z" : "nz");
1560 /* Note: these assume appropriate adjustments were made so that
1561 unsigned comparisons, which is all this chip has, will
1565 fprintf (file
, "#comparison eliminated");
1567 fprintf (file
, letter
== 'c' ? "nc" : "c");
1571 fprintf (file
, "br");
1573 fprintf (file
, letter
== 'c' ? "h" : "nh");
1577 fprintf (file
, "br");
1579 fprintf (file
, letter
== 'c' ? "c" : "nc");
1583 fprintf (file
, "#comparison eliminated");
1585 fprintf (file
, letter
== 'c' ? "nh" : "h");
1589 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1594 #undef TARGET_PRINT_OPERAND
1595 #define TARGET_PRINT_OPERAND rl78_print_operand
1598 rl78_print_operand (FILE * file
, rtx op
, int letter
)
1600 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S')
1601 fprintf (file
, "#");
1602 rl78_print_operand_1 (file
, op
, letter
);
1605 #undef TARGET_TRAMPOLINE_INIT
1606 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1608 /* Note that the RL78's addressing makes it very difficult to do
1609 trampolines on the stack. So, libgcc has a small pool of
1610 trampolines from which one is allocated to this task. */
1612 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
1614 rtx mov_addr
, thunk_addr
;
1615 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
1617 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
1618 thunk_addr
= gen_reg_rtx (HImode
);
1620 function
= force_reg (HImode
, function
);
1621 static_chain
= force_reg (HImode
, static_chain
);
1623 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
1624 emit_move_insn (mov_addr
, thunk_addr
);
1626 cfun
->machine
->trampolines_used
= 1;
1629 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1630 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1633 rl78_trampoline_adjust_address (rtx m_tramp
)
1635 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
1639 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1640 the "normal" compares, specifically, it only has unsigned compares,
1641 so we must synthesize the missing ones. */
1643 rl78_expand_compare (rtx
*operands
)
1645 if (GET_CODE (operands
[2]) == MEM
)
1646 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
1651 /* Define this to 1 if you are debugging the peephole optimizers. */
1652 #define DEBUG_PEEP 0
1654 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1655 The default "word" size is a byte so we can effectively use all the
1656 registers, but we want to do 16-bit moves whenever possible. This
1657 function determines when such a move is an option. */
1659 rl78_peep_movhi_p (rtx
*operands
)
1664 /* (set (op0) (op1))
1665 (set (op2) (op3)) */
1668 fprintf (stderr
, "\033[33m");
1669 debug_rtx (operands
[0]);
1670 debug_rtx (operands
[1]);
1671 debug_rtx (operands
[2]);
1672 debug_rtx (operands
[3]);
1673 fprintf (stderr
, "\033[0m");
1676 /* You can move a constant to memory as QImode, but not HImode. */
1677 if (GET_CODE (operands
[0]) == MEM
1678 && GET_CODE (operands
[1]) != REG
)
1681 fprintf (stderr
, "no peep: move constant to memory\n");
1686 if (rtx_equal_p (operands
[0], operands
[3]))
1689 fprintf (stderr
, "no peep: overlapping\n");
1694 for (i
= 0; i
< 2; i
++)
1696 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
1699 fprintf (stderr
, "no peep: different codes\n");
1703 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
1706 fprintf (stderr
, "no peep: different modes\n");
1711 switch (GET_CODE (operands
[i
]))
1715 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
1716 || GET_MODE (operands
[i
]) != QImode
)
1719 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
1720 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
1725 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
1728 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
1738 if (GET_MODE (operands
[i
]) != QImode
)
1740 if (MEM_ALIGN (operands
[i
]) < 16)
1742 a
= XEXP (operands
[i
], 0);
1743 if (GET_CODE (a
) == CONST
)
1745 if (GET_CODE (a
) == PLUS
)
1747 if (GET_CODE (a
) == CONST_INT
1751 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
1752 debug_rtx (operands
[i
]);
1756 m
= adjust_address (operands
[i
], QImode
, 1);
1757 if (! rtx_equal_p (m
, operands
[i
+2]))
1760 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
1762 debug_rtx (operands
[i
+2]);
1770 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
1776 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
1781 /* Likewise, when a peephole is activated, this function helps compute
1782 the new operands. */
1784 rl78_setup_peep_movhi (rtx
*operands
)
1788 for (i
= 0; i
< 2; i
++)
1790 switch (GET_CODE (operands
[i
]))
1793 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
1797 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char)INTVAL (operands
[i
+2])) * 256);
1801 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
1811 How Devirtualization works in the RL78 GCC port
1815 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1816 bytes of register space, in four banks, memory-mapped. One bank is
1817 the "selected" bank and holds the registers used for primary
1818 operations. Since the registers are memory mapped, often you can
1819 still refer to the unselected banks via memory accesses.
1823 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1824 and refers to the other banks via their memory addresses, although
1825 they're treated as regular registers internally. These "virtual"
1826 registers are R8 through R23 (bank3 is reserved for asm-based
1827 interrupt handlers).
1829 There are four machine description files:
1831 rl78.md - common register-independent patterns and definitions
1832 rl78-expand.md - expanders
1833 rl78-virt.md - patterns that match BEFORE devirtualization
1834 rl78-real.md - patterns that match AFTER devirtualization
1836 At least through register allocation and reload, gcc is told that it
1837 can do pretty much anything - but may only use the virtual registers.
1838 GCC cannot properly create the varying addressing modes that the RL78
1839 supports in an efficient way.
1841 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1842 uses the "valloc" attribute in rl78-virt.md for determining the rules
1843 by which it will replace virtual registers with real registers (or
1844 not) and how to make up addressing modes. For example, insns tagged
1845 with "ro1" have a single read-only parameter, which may need to be
1846 moved from memory/constant/vreg to a suitable real register. As part
1847 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1848 patterns and enabling the rl78-real.md patterns. The new patterns'
1849 constraints are used to determine the real registers used. NOTE:
1850 patterns in rl78-virt.md essentially ignore the constrains and rely on
1851 predicates, where the rl78-real.md ones essentially ignore the
1852 predicates and rely on the constraints.
1854 The devirtualization pass is scheduled via the pass manager (despite
1855 being called "rl78_reorg") so it can be scheduled prior to var-track
1856 (the idea is to let gdb know about the new registers). Ideally, it
1857 would be scheduled right after pro/epilogue generation, so the
1858 post-reload optimizers could operate on the real registers, but when I
1859 tried that there were some issues building the target libraries.
1861 During devirtualization, a simple register move optimizer is run. It
1862 would be better to run a full CSE/propogation pass on it through, or
1863 re-run regmove, but that has not yet been attempted.
1866 #define DEBUG_ALLOC 0
1868 #define OP(x) (*recog_data.operand_loc[x])
1870 /* This array is used to hold knowledge about the contents of the
1871 real registers (A ... H), the memory-based registers (r8 ... r31)
1872 and the first NUM_STACK_LOCS words on the stack. We use this to
1873 avoid generating redundant move instructions.
1875 A value in the range 0 .. 31 indicates register A .. r31.
1876 A value in the range 32 .. 63 indicates stack slot (value - 32).
1877 A value of NOT_KNOWN indicates that the contents of that location
1880 #define NUM_STACK_LOCS 32
1881 #define NOT_KNOWN 127
1883 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
1885 static unsigned char saved_update_index
= NOT_KNOWN
;
1886 static unsigned char saved_update_value
;
1887 static enum machine_mode saved_update_mode
;
1891 clear_content_memory (void)
1893 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
1895 fprintf (dump_file
, " clear content memory\n");
1896 saved_update_index
= NOT_KNOWN
;
1899 /* Convert LOC into an index into the content_memory array.
1900 If LOC cannot be converted, return NOT_KNOWN. */
1902 static unsigned char
1903 get_content_index (rtx loc
)
1905 enum machine_mode mode
;
1907 if (loc
== NULL_RTX
)
1912 if (REGNO (loc
) < 32)
1917 mode
= GET_MODE (loc
);
1919 if (! rl78_stack_based_mem (loc
, mode
))
1922 loc
= XEXP (loc
, 0);
1925 /* loc = MEM (SP) */
1928 /* loc = MEM (PLUS (SP, INT)). */
1929 loc
= XEXP (loc
, 1);
1931 if (INTVAL (loc
) < NUM_STACK_LOCS
)
1932 return 32 + INTVAL (loc
);
1937 /* Return a string describing content INDEX in mode MODE.
1938 WARNING: Can return a pointer to a static buffer. */
1941 get_content_name (unsigned char index
, enum machine_mode mode
)
1943 static char buffer
[128];
1945 if (index
== NOT_KNOWN
)
1949 sprintf (buffer
, "stack slot %d", index
- 32);
1950 else if (mode
== HImode
)
1951 sprintf (buffer
, "%s%s",
1952 reg_names
[index
+ 1], reg_names
[index
]);
1954 return reg_names
[index
];
1962 display_content_memory (FILE * file
)
1966 fprintf (file
, " Known memory contents:\n");
1968 for (i
= 0; i
< sizeof content_memory
; i
++)
1969 if (content_memory
[i
] != NOT_KNOWN
)
1971 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
1972 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
1978 update_content (unsigned char index
, unsigned char val
, enum machine_mode mode
)
1982 gcc_assert (index
< sizeof content_memory
);
1984 content_memory
[index
] = val
;
1985 if (val
!= NOT_KNOWN
)
1986 content_memory
[val
] = index
;
1988 /* Make the entry in dump_file *before* VAL is increased below. */
1991 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
1992 if (val
== NOT_KNOWN
)
1993 fprintf (dump_file
, "Unknown\n");
1995 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2000 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2002 content_memory
[index
+ 1] = val
;
2003 if (val
!= NOT_KNOWN
)
2005 content_memory
[val
] = index
+ 1;
2010 /* Any other places that had INDEX recorded as their contents are now invalid. */
2011 for (i
= 0; i
< sizeof content_memory
; i
++)
2014 || (val
!= NOT_KNOWN
&& i
== val
))
2021 if (content_memory
[i
] == index
2022 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2024 content_memory
[i
] = NOT_KNOWN
;
2027 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2030 content_memory
[++ i
] = NOT_KNOWN
;
2035 /* Record that LOC contains VALUE.
2036 For HImode locations record that LOC+1 contains VALUE+1.
2037 If LOC is not a register or stack slot, do nothing.
2038 If VALUE is not a register or stack slot, clear the recorded content. */
2041 record_content (rtx loc
, rtx value
)
2043 enum machine_mode mode
;
2044 unsigned char index
;
2047 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2050 val
= get_content_index (value
);
2052 mode
= GET_MODE (loc
);
2059 /* This should not happen when optimizing. */
2061 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2062 get_content_name (val
, mode
));
2069 update_content (index
, val
, mode
);
2072 /* Returns TRUE if LOC already contains a copy of VALUE. */
2075 already_contains (rtx loc
, rtx value
)
2077 unsigned char index
;
2080 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2083 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2086 if (content_memory
[index
] != val
)
2089 if (GET_MODE (loc
) == HImode
)
2090 return content_memory
[index
+ 1] == val
+ 1;
2096 rl78_es_addr (rtx addr
)
2098 if (GET_CODE (addr
) == MEM
)
2099 addr
= XEXP (addr
, 0);
2100 if (GET_CODE (addr
) != UNSPEC
)
2102 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2108 rl78_es_base (rtx addr
)
2110 if (GET_CODE (addr
) == MEM
)
2111 addr
= XEXP (addr
, 0);
2112 addr
= XVECEXP (addr
, 0, 1);
2113 if (GET_CODE (addr
) == CONST
2114 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2115 addr
= XEXP (XEXP (addr
, 0), 0);
2116 /* Mode doesn't matter here. */
2117 return gen_rtx_MEM (HImode
, addr
);
2120 /* Rescans an insn to see if it's recognized again. This is done
2121 carefully to ensure that all the constraint information is accurate
2122 for the newly matched insn. */
2124 insn_ok_now (rtx insn
)
2126 rtx pattern
= PATTERN (insn
);
2129 INSN_CODE (insn
) = -1;
2131 if (recog (pattern
, insn
, 0) > -1)
2133 extract_insn (insn
);
2134 if (constrain_operands (1))
2137 fprintf (stderr
, "\033[32m");
2139 fprintf (stderr
, "\033[0m");
2141 if (SET_P (pattern
))
2142 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2144 /* We need to detect far addresses that haven't been
2145 converted to es/lo16 format. */
2146 for (i
=0; i
<recog_data
.n_operands
; i
++)
2147 if (GET_CODE (OP(i
)) == MEM
2148 && GET_MODE (XEXP (OP(i
), 0)) == SImode
2149 && GET_CODE (XEXP (OP(i
), 0)) != UNSPEC
)
2157 /* We need to re-recog the insn with virtual registers to get
2159 cfun
->machine
->virt_insns_ok
= 1;
2160 if (recog (pattern
, insn
, 0) > -1)
2162 extract_insn (insn
);
2163 if (constrain_operands (0))
2165 cfun
->machine
->virt_insns_ok
= 0;
2171 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2178 fprintf (stderr
, "\033[31m");
2180 fprintf (stderr
, "\033[0m");
2186 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2187 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2188 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2189 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2190 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2192 #define FAILED gcc_unreachable ()
2193 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2194 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2197 /* Registers into which we move the contents of virtual registers. */
2198 #define X gen_rtx_REG (QImode, 0)
2199 #define A gen_rtx_REG (QImode, 1)
2200 #define C gen_rtx_REG (QImode, 2)
2201 #define B gen_rtx_REG (QImode, 3)
2202 #define E gen_rtx_REG (QImode, 4)
2203 #define D gen_rtx_REG (QImode, 5)
2204 #define L gen_rtx_REG (QImode, 6)
2205 #define H gen_rtx_REG (QImode, 7)
2207 #define AX gen_rtx_REG (HImode, 0)
2208 #define BC gen_rtx_REG (HImode, 2)
2209 #define DE gen_rtx_REG (HImode, 4)
2210 #define HL gen_rtx_REG (HImode, 6)
2212 /* Returns TRUE if R is a virtual register. */
2214 is_virtual_register (rtx r
)
2216 return (GET_CODE (r
) == REG
2221 /* In all these alloc routines, we expect the following: the insn
2222 pattern is unshared, the insn was previously recognized and failed
2223 due to predicates or constraints, and the operand data is in
2226 static int virt_insn_was_frame
;
2228 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2231 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2234 fprintf (stderr
, "\033[36m%d: ", line
);
2236 fprintf (stderr
, "\033[0m");
2238 /*SCHED_GROUP_P (r) = 1;*/
2239 if (virt_insn_was_frame
)
2240 RTX_FRAME_RELATED_P (r
) = 1;
2244 #define EM(x) EM2 (__LINE__, x)
2246 /* Return a suitable RTX for the low half of a __far address. */
2248 rl78_lo16 (rtx addr
)
2252 if (GET_CODE (addr
) == SYMBOL_REF
2253 || GET_CODE (addr
) == CONST
)
2255 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2256 r
= gen_rtx_CONST (HImode
, r
);
2259 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2261 r
= gen_es_addr (r
);
2266 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2270 if (GET_CODE (addr
) == SYMBOL_REF
2271 || GET_CODE (addr
) == CONST
)
2273 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2274 r
= gen_rtx_CONST (QImode
, r
);
2277 return rl78_subreg (QImode
, addr
, SImode
, 2);
2281 add_postponed_content_update (rtx to
, rtx value
)
2283 unsigned char index
;
2285 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2288 gcc_assert (saved_update_index
== NOT_KNOWN
);
2289 saved_update_index
= index
;
2290 saved_update_value
= get_content_index (value
);
2291 saved_update_mode
= GET_MODE (to
);
2295 process_postponed_content_update (void)
2297 if (saved_update_index
!= NOT_KNOWN
)
2299 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2300 saved_update_index
= NOT_KNOWN
;
2304 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2305 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2306 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2307 BEFORE is true, FROM otherwise. */
2309 gen_and_emit_move (rtx to
, rtx from
, rtx where
, bool before
)
2311 enum machine_mode mode
= GET_MODE (to
);
2313 if (optimize
&& before
&& already_contains (to
, from
))
2316 display_content_memory (stderr
);
2320 fprintf (dump_file
, " Omit move of %s into ",
2321 get_content_name (get_content_index (from
), mode
));
2322 fprintf (dump_file
, "%s as it already contains this value\n",
2323 get_content_name (get_content_index (to
), mode
));
2328 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2332 if (where
== NULL_RTX
)
2335 emit_insn_before (move
, where
);
2338 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2340 /* If necessary move REG_EH_REGION notes forward.
2341 cf. compiling gcc.dg/pr44545.c. */
2342 if (note
!= NULL_RTX
)
2344 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2345 remove_note (where
, note
);
2348 emit_insn_after (move
, where
);
2352 record_content (to
, from
);
2354 add_postponed_content_update (to
, from
);
2356 return before
? to
: from
;
2359 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2360 copy it into NEWBASE and return the updated MEM. Otherwise just
2361 return M. Any needed insns are emitted before BEFORE. */
2363 transcode_memory_rtx (rtx m
, rtx newbase
, rtx before
)
2365 rtx base
, index
, addendr
;
2372 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2374 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2376 fprintf (stderr
, "setting ES:\n");
2379 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2380 emit_insn_before (EM (gen_movqi_es (A
)), before
);
2381 record_content (A
, NULL_RTX
);
2383 m
= change_address (m
, GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2387 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2388 gcc_assert (index
== NULL_RTX
);
2391 fprintf (stderr
, "\033[33m"); debug_rtx (m
); fprintf (stderr
, "\033[0m");
2394 if (base
== NULL_RTX
)
2397 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2398 addend
= INTVAL (addendr
);
2400 gcc_assert (REG_P (base
));
2401 gcc_assert (REG_P (newbase
));
2403 if (REGNO (base
) == SP_REG
)
2405 if (addend
>= 0 && addend
<= 255)
2409 /* BASE should be a virtual register. We copy it to NEWBASE. If
2410 the addend is out of range for DE/HL, we use AX to compute the full
2414 || (addend
> 255 && REGNO (newbase
) != 2)
2415 || (addendr
&& GET_CODE (addendr
) != CONST_INT
))
2420 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2421 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2422 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2423 record_content (AX
, NULL_RTX
);
2424 record_content (newbase
, NULL_RTX
);
2431 base
= gen_and_emit_move (newbase
, base
, before
, true);
2436 record_content (base
, NULL_RTX
);
2437 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2441 fprintf (stderr
, "\033[33m");
2445 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2447 m
= change_address (m
, GET_MODE (m
), base
);
2450 fprintf (stderr
, "\033[0m");
2455 /* Copy SRC to accumulator (A or AX), placing any generated insns
2456 before BEFORE. Returns accumulator RTX. */
2459 move_to_acc (int opno
, rtx before
)
2461 rtx src
= OP (opno
);
2462 enum machine_mode mode
= GET_MODE (src
);
2464 if (REG_P (src
) && REGNO (src
) < 2)
2467 if (mode
== VOIDmode
)
2468 mode
= recog_data
.operand_mode
[opno
];
2470 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2474 force_into_acc (rtx src
, rtx before
)
2476 enum machine_mode mode
= GET_MODE (src
);
2479 if (REG_P (src
) && REGNO (src
) < 2)
2482 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2486 emit_insn_before (move
, before
);
2487 record_content (AX
, NULL_RTX
);
2490 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2491 after AFTER. Returns accumulator RTX. */
2494 move_from_acc (unsigned int opno
, rtx after
)
2496 rtx dest
= OP (opno
);
2497 enum machine_mode mode
= GET_MODE (dest
);
2499 if (REG_P (dest
) && REGNO (dest
) < 2)
2502 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2505 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2506 before BEFORE. Returns reg RTX. */
2509 move_acc_to_reg (rtx acc
, int regno
, rtx before
)
2511 enum machine_mode mode
= GET_MODE (acc
);
2514 reg
= gen_rtx_REG (mode
, regno
);
2516 return gen_and_emit_move (reg
, acc
, before
, true);
2519 /* Copy SRC to X, placing any generated insns before BEFORE.
2523 move_to_x (int opno
, rtx before
)
2525 rtx src
= OP (opno
);
2526 enum machine_mode mode
= GET_MODE (src
);
2529 if (mode
== VOIDmode
)
2530 mode
= recog_data
.operand_mode
[opno
];
2531 reg
= (mode
== QImode
) ? X
: AX
;
2533 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2535 OP (opno
) = move_to_acc (opno
, before
);
2536 OP (opno
) = move_acc_to_reg (OP(opno
), X_REG
, before
);
2540 return gen_and_emit_move (reg
, src
, before
, true);
2543 /* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
2544 Returns H/HL RTX. */
2547 move_to_hl (int opno
, rtx before
)
2549 rtx src
= OP (opno
);
2550 enum machine_mode mode
= GET_MODE (src
);
2553 if (mode
== VOIDmode
)
2554 mode
= recog_data
.operand_mode
[opno
];
2555 reg
= (mode
== QImode
) ? L
: HL
;
2557 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2559 OP (opno
) = move_to_acc (opno
, before
);
2560 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
2564 return gen_and_emit_move (reg
, src
, before
, true);
2567 /* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
2568 Returns E/DE RTX. */
2571 move_to_de (int opno
, rtx before
)
2573 rtx src
= OP (opno
);
2574 enum machine_mode mode
= GET_MODE (src
);
2577 if (mode
== VOIDmode
)
2578 mode
= recog_data
.operand_mode
[opno
];
2580 reg
= (mode
== QImode
) ? E
: DE
;
2582 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2584 OP (opno
) = move_to_acc (opno
, before
);
2585 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
2589 gen_and_emit_move (reg
, src
, before
, true);
2595 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2597 rl78_alloc_physical_registers_op1 (rtx insn
)
2599 /* op[0] = func op[1] */
2601 /* We first try using A as the destination, then copying it
2603 if (rtx_equal_p (OP (0), OP (1)))
2606 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2610 /* If necessary, load the operands into BC and HL.
2611 Check to see if we already have OP (0) in HL
2612 and if so, swap the order. */
2614 && already_contains (HL
, XEXP (OP (0), 0)))
2616 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
2617 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
2621 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2622 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
2628 OP (0) = move_from_acc (0, insn
);
2632 /* Try copying the src to acc first, then. This is for, for
2633 example, ZERO_EXTEND or NOT. */
2634 OP (1) = move_to_acc (1, insn
);
2639 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2640 Assumes that the current insn has already been recognised and hence the
2641 constraint data has been filled in. */
2643 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
2645 const char * p
= recog_data
.constraints
[opnum
];
2647 /* No constraints means anything is accepted. */
2648 if (p
== NULL
|| *p
== 0 || *p
== ',')
2657 len
= CONSTRAINT_LEN (c
, p
);
2658 gcc_assert (len
> 0);
2666 if (lookup_constraint (p
) == constraint
)
2674 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2676 rl78_alloc_physical_registers_op2 (rtx insn
)
2684 if (rtx_equal_p (OP (0), OP (1)))
2687 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2688 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2690 else if (rtx_equal_p (OP (0), OP (2)))
2692 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2694 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2698 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2699 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2700 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2705 prev
= prev_nonnote_nondebug_insn (insn
);
2706 if (recog_data
.constraints
[1][0] == '%'
2707 && is_virtual_register (OP (1))
2708 && ! is_virtual_register (OP (2))
2709 && ! CONSTANT_P (OP (2)))
2716 /* Make a note of whether (H)L is being used. It matters
2717 because if OP (2) alsoneeds reloading, then we must take
2718 care not to corrupt HL. */
2719 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
2721 /* If HL is not currently being used and dest == op1 then there are
2722 some possible optimizations available by reloading one of the
2723 operands into HL, before trying to use the accumulator. */
2726 && rtx_equal_p (OP (0), OP (1)))
2728 /* If op0 is a Ws1 type memory address then switching the base
2729 address register to HL might allow us to perform an in-memory
2730 operation. (eg for the INCW instruction).
2732 FIXME: Adding the move into HL is costly if this optimization is not
2733 going to work, so for now, make sure that we know that the new insn will
2734 match the requirements of the addhi3_real pattern. Really we ought to
2735 generate a candidate sequence, test that, and then install it if the
2736 results are good. */
2737 if (satisfies_constraint_Ws1 (OP (0))
2738 && has_constraint (0, CONSTRAINT_Wh1
)
2739 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2741 rtx base
, index
, addend
, newbase
;
2743 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
2744 gcc_assert (index
== NULL_RTX
);
2745 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2747 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2748 if (addend
!= NULL_RTX
)
2750 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
2751 record_content (newbase
, NULL_RTX
);
2752 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
2754 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
2756 /* We do not want to fail here as this means that
2757 we have inserted useless insns into the stream. */
2761 else if (REG_P (OP (0))
2762 && satisfies_constraint_Ws1 (OP (2))
2763 && has_constraint (2, CONSTRAINT_Wh1
))
2765 rtx base
, index
, addend
, newbase
;
2767 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
2768 gcc_assert (index
== NULL_RTX
);
2769 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2771 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2772 if (addend
!= NULL_RTX
)
2774 gen_and_emit_move (HL
, base
, insn
, true);
2776 if (REGNO (OP (0)) != X_REG
)
2778 OP (1) = move_to_acc (1, insn
);
2779 OP (0) = move_from_acc (0, insn
);
2782 record_content (HL
, NULL_RTX
);
2783 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
2785 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
2787 /* We do not want to fail here as this means that
2788 we have inserted useless insns into the stream. */
2795 OP (0) = move_from_acc (0, insn
);
2797 tmp_id
= get_max_insn_count ();
2800 if (rtx_equal_p (OP (1), OP (2)))
2801 OP (2) = OP (1) = move_to_acc (1, insn
);
2803 OP (1) = move_to_acc (1, insn
);
2807 /* If we omitted the move of OP1 into the accumulator (because
2808 it was already there from a previous insn), then force the
2809 generation of the move instruction now. We know that we
2810 are about to emit a move into HL (or DE) via AX, and hence
2811 our optimization to remove the load of OP1 is no longer valid. */
2812 if (tmp_id
== get_max_insn_count ())
2813 force_into_acc (saved_op1
, insn
);
2815 /* We have to copy op2 to HL (or DE), but that involves AX, which
2816 already has a live value. Emit it before those insns. */
2819 first
= next_nonnote_nondebug_insn (prev
);
2821 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2824 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
2829 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2832 rl78_alloc_physical_registers_ro1 (rtx insn
)
2834 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2838 OP (0) = move_to_acc (0, insn
);
2843 /* Devirtualize a compare insn. */
2846 rl78_alloc_physical_registers_cmp (rtx insn
)
2850 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2853 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2854 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2856 /* HI compares have to have OP(1) in AX, but QI
2857 compares do not, so it is worth checking here. */
2860 /* For an HImode compare, OP(1) must always be in AX.
2861 But if OP(1) is a REG (and not AX), then we can avoid
2862 a reload of OP(1) if we reload OP(2) into AX and invert
2865 && REGNO (OP (1)) != AX_REG
2866 && GET_MODE (OP (1)) == HImode
2869 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
2871 OP (2) = move_to_acc (2, insn
);
2873 switch (GET_CODE (cmp
))
2878 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
2879 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
2880 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
2881 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
2894 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
2895 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
2897 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
2902 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2903 should be handled by the second alternative of the cbranchhi_real pattern. */
2904 if (rtx_equal_p (OP (1), OP (2)))
2906 OP (1) = OP (2) = BC
;
2910 tmp_id
= get_max_insn_count ();
2913 OP (1) = move_to_acc (1, insn
);
2917 /* If we omitted the move of OP1 into the accumulator (because
2918 it was already there from a previous insn), then force the
2919 generation of the move instruction now. We know that we
2920 are about to emit a move into HL via AX, and hence our
2921 optimization to remove the load of OP1 is no longer valid. */
2922 if (tmp_id
== get_max_insn_count ())
2923 force_into_acc (saved_op1
, insn
);
2925 /* We have to copy op2 to HL, but that involves the acc, which
2926 already has a live value. Emit it before those insns. */
2928 first
= next_nonnote_nondebug_insn (prev
);
2930 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2932 OP (2) = move_to_hl (2, first
);
2937 /* Like op2, but AX = A op X. */
2940 rl78_alloc_physical_registers_umul (rtx insn
)
2942 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2947 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2948 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2949 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2953 if (recog_data
.constraints
[1][0] == '%'
2954 && is_virtual_register (OP (1))
2955 && !is_virtual_register (OP (2))
2956 && !CONSTANT_P (OP (2)))
2963 OP (0) = move_from_acc (0, insn
);
2965 tmp_id
= get_max_insn_count ();
2968 OP (1) = move_to_acc (1, insn
);
2972 /* If we omitted the move of OP1 into the accumulator (because
2973 it was already there from a previous insn), then force the
2974 generation of the move instruction now. We know that we
2975 are about to emit a move into HL (or DE) via AX, and hence
2976 our optimization to remove the load of OP1 is no longer valid. */
2977 if (tmp_id
== get_max_insn_count ())
2978 force_into_acc (saved_op1
, insn
);
2980 /* We have to copy op2 to X, but that involves the acc, which
2981 already has a live value. Emit it before those insns. */
2984 first
= next_nonnote_nondebug_insn (prev
);
2986 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2988 OP (2) = move_to_x (2, first
);
2994 rl78_alloc_address_registers_macax (rtx insn
)
2997 bool replace_in_op0
= false;
2998 bool replace_in_op1
= false;
3002 /* Two different MEMs are not allowed. */
3004 for (op
= 2; op
>= 0; op
--)
3006 if (MEM_P (OP (op
)))
3008 if (op
== 0 && replace_in_op0
)
3010 if (op
== 1 && replace_in_op1
)
3016 /* If we replace a MEM, make sure that we replace it for all
3017 occurrences of the same MEM in the insn. */
3018 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3019 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3021 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3024 && (REGNO (XEXP (OP (op
), 0)) == SP_REG
3025 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3026 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3028 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3029 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3037 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3040 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3049 /* Scan all insns and devirtualize them. */
3051 rl78_alloc_physical_registers (void)
3053 /* During most of the compile, gcc is dealing with virtual
3054 registers. At this point, we need to assign physical registers
3055 to the vitual ones, and copy in/out as needed. */
3058 enum attr_valloc valloc_method
;
3060 for (insn
= get_insns (); insn
; insn
= curr
)
3064 curr
= next_nonnote_nondebug_insn (insn
);
3067 && (GET_CODE (PATTERN (insn
)) == SET
3068 || GET_CODE (PATTERN (insn
)) == CALL
)
3069 && INSN_CODE (insn
) == -1)
3071 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3073 i
= recog (PATTERN (insn
), insn
, 0);
3079 INSN_CODE (insn
) = i
;
3083 cfun
->machine
->virt_insns_ok
= 0;
3084 cfun
->machine
->real_insns_ok
= 1;
3086 clear_content_memory ();
3088 for (insn
= get_insns (); insn
; insn
= curr
)
3092 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3097 clear_content_memory ();
3103 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3105 pattern
= PATTERN (insn
);
3106 if (GET_CODE (pattern
) == PARALLEL
)
3107 pattern
= XVECEXP (pattern
, 0, 0);
3108 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3109 clear_content_memory ();
3110 if (GET_CODE (pattern
) != SET
3111 && GET_CODE (pattern
) != CALL
)
3113 if (GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3116 valloc_method
= get_attr_valloc (insn
);
3118 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3120 if (valloc_method
== VALLOC_MACAX
)
3122 record_content (AX
, NULL_RTX
);
3123 record_content (BC
, NULL_RTX
);
3124 record_content (DE
, NULL_RTX
);
3127 if (insn_ok_now (insn
))
3130 INSN_CODE (insn
) = -1;
3132 if (RTX_FRAME_RELATED_P (insn
))
3133 virt_insn_was_frame
= 1;
3135 virt_insn_was_frame
= 0;
3137 switch (valloc_method
)
3140 rl78_alloc_physical_registers_op1 (insn
);
3143 rl78_alloc_physical_registers_op2 (insn
);
3146 rl78_alloc_physical_registers_ro1 (insn
);
3149 rl78_alloc_physical_registers_cmp (insn
);
3152 rl78_alloc_physical_registers_umul (insn
);
3155 /* Macro that clobbers AX. */
3156 rl78_alloc_address_registers_macax (insn
);
3157 record_content (AX
, NULL_RTX
);
3158 record_content (BC
, NULL_RTX
);
3159 record_content (DE
, NULL_RTX
);
3163 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3164 clear_content_memory ();
3166 process_postponed_content_update ();
3169 fprintf (stderr
, "\033[0m");
3173 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3174 This function scans for uses of registers; the last use (i.e. first
3175 encounter when scanning backwards) triggers a REG_DEAD note if the
3176 reg was previously in DEAD[]. */
3178 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3187 code
= GET_CODE (s
);
3191 /* Compare registers by number. */
3196 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3197 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3198 print_rtl_single (dump_file
, s
);
3201 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3202 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3206 /* These codes have no constituent expressions
3217 /* These are kept unique for a given value. */
3224 fmt
= GET_RTX_FORMAT (code
);
3226 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3231 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3232 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3234 else if (fmt
[i
] == 'e')
3235 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3239 /* Like the previous function, but scan for SETs instead. */
3241 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3245 if (GET_CODE (d
) != REG
)
3250 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3252 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3253 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3257 /* This is a rather crude register death pass. Death status is reset
3258 at every jump or call insn. */
3260 rl78_calculate_death_notes (void)
3262 char dead
[FIRST_PSEUDO_REGISTER
];
3266 memset (dead
, 0, sizeof (dead
));
3268 for (insn
= get_last_insn ();
3270 insn
= prev_nonnote_nondebug_insn (insn
))
3274 fprintf (dump_file
, "\n--------------------------------------------------");
3275 fprintf (dump_file
, "\nDead:");
3276 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3278 fprintf (dump_file
, " %s", reg_names
[i
]);
3279 fprintf (dump_file
, "\n");
3280 print_rtl_single (dump_file
, insn
);
3283 switch (GET_CODE (insn
))
3287 switch (GET_CODE (p
))
3292 rl78_note_reg_set (dead
, d
, insn
);
3293 rl78_note_reg_uses (dead
, s
, insn
);
3297 rl78_note_reg_uses (dead
, p
, insn
);
3306 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3308 memset (dead
, 1, sizeof (dead
));
3309 /* We expect a USE just prior to this, which will mark
3310 the actual return registers. The USE will have a
3311 death note, but we aren't going to be modifying it
3316 memset (dead
, 0, sizeof (dead
));
3323 print_rtl_single (dump_file
, insn
);
3327 /* Helper function to reset the origins in RP and the age in AGE for
3330 reset_origins (int *rp
, int *age
)
3333 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3340 /* The idea behind this optimization is to look for cases where we
3341 move data from A to B to C, and instead move from A to B, and A to
3342 C. If B is a virtual register or memory, this is a big win on its
3343 own. If B turns out to be unneeded after this, it's a bigger win.
3344 For each register, we try to determine where it's value originally
3345 came from, if it's propogated purely through moves (and not
3346 computes). The ORIGINS[] array has the regno for the "origin" of
3347 the value in the [regno] it's indexed by. */
3349 rl78_propogate_register_origins (void)
3351 int origins
[FIRST_PSEUDO_REGISTER
];
3352 int age
[FIRST_PSEUDO_REGISTER
];
3354 rtx insn
, ninsn
= NULL_RTX
;
3357 reset_origins (origins
, age
);
3359 for (insn
= get_insns (); insn
; insn
= ninsn
)
3361 ninsn
= next_nonnote_nondebug_insn (insn
);
3365 fprintf (dump_file
, "\n");
3366 fprintf (dump_file
, "Origins:");
3367 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3368 if (origins
[i
] != i
)
3369 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
3370 fprintf (dump_file
, "\n");
3371 print_rtl_single (dump_file
, insn
);
3374 switch (GET_CODE (insn
))
3380 reset_origins (origins
, age
);
3387 pat
= PATTERN (insn
);
3389 if (GET_CODE (pat
) == PARALLEL
)
3391 rtx clobber
= XVECEXP (pat
, 0, 1);
3392 pat
= XVECEXP (pat
, 0, 0);
3393 if (GET_CODE (clobber
) == CLOBBER
)
3395 int cr
= REGNO (XEXP (clobber
, 0));
3396 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
3398 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
3399 for (i
= 0; i
< mb
; i
++)
3401 origins
[cr
+ i
] = cr
+ i
;
3409 if (GET_CODE (pat
) == SET
)
3411 rtx src
= SET_SRC (pat
);
3412 rtx dest
= SET_DEST (pat
);
3413 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3415 if (GET_CODE (dest
) == REG
)
3417 int dr
= REGNO (dest
);
3419 if (GET_CODE (src
) == REG
)
3421 int sr
= REGNO (src
);
3423 int best_age
, best_reg
;
3425 /* See if the copy is not needed. */
3426 for (i
= 0; i
< mb
; i
++)
3427 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3432 fprintf (dump_file
, "deleting because dest already has correct value\n");
3437 if (dr
< 8 || sr
>= 8)
3443 /* See if the copy can be made from another
3444 bank 0 register instead, instead of the
3445 virtual src register. */
3446 for (ar
= 0; ar
< 8; ar
+= mb
)
3449 for (i
= 0; i
< mb
; i
++)
3450 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3453 /* The chip has some reg-reg move limitations. */
3454 if (mb
== 1 && dr
> 3)
3459 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3461 best_age
= age
[sr
+ i
];
3469 /* FIXME: copy debug info too. */
3470 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3475 for (i
= 0; i
< mb
; i
++)
3477 origins
[dr
+ i
] = origins
[sr
+ i
];
3478 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3483 /* The destination is computed, its origin is itself. */
3485 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3486 dr
, mb
, mb
== 1 ? "" : "s");
3487 for (i
= 0; i
< mb
; i
++)
3489 origins
[dr
+ i
] = dr
+ i
;
3494 /* Any registers marked with that reg as an origin are reset. */
3495 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3496 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3503 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3504 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3507 fprintf (dump_file
, "Resetting origin of AX/BC for macro.\n");
3508 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3509 if (i
<= 3 || origins
[i
] <= 3)
3516 if (GET_CODE (src
) == ASHIFT
3517 || GET_CODE (src
) == ASHIFTRT
3518 || GET_CODE (src
) == LSHIFTRT
)
3520 rtx count
= XEXP (src
, 1);
3521 if (GET_CODE (count
) == REG
)
3523 /* Special case - our pattern clobbers the count register. */
3524 int r
= REGNO (count
);
3526 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
3527 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3528 if (i
== r
|| origins
[i
] == r
)
3540 /* Remove any SETs where the destination is unneeded. */
3542 rl78_remove_unused_sets (void)
3544 rtx insn
, ninsn
= NULL_RTX
;
3547 for (insn
= get_insns (); insn
; insn
= ninsn
)
3549 ninsn
= next_nonnote_nondebug_insn (insn
);
3551 if ((insn
= single_set (insn
)) == NULL_RTX
)
3554 dest
= SET_DEST (insn
);
3556 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
3559 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
3564 /* This is the top of the devritualization pass. */
3568 /* split2 only happens when optimizing, but we need all movSIs to be
3573 rl78_alloc_physical_registers ();
3577 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3578 print_rtl_with_bb (dump_file
, get_insns (), 0);
3581 rl78_propogate_register_origins ();
3582 rl78_calculate_death_notes ();
3586 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3587 print_rtl_with_bb (dump_file
, get_insns (), 0);
3588 fprintf (dump_file
, "\n======================================================================\n");
3591 rl78_remove_unused_sets ();
3593 /* The code after devirtualizing has changed so much that at this point
3594 we might as well just rescan everything. Note that
3595 df_rescan_all_insns is not going to help here because it does not
3596 touch the artificial uses and defs. */
3597 df_finish_pass (true);
3599 df_live_add_problem ();
3600 df_scan_alloc (NULL
);
3607 #undef TARGET_RETURN_IN_MEMORY
3608 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3611 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
3613 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
3614 return (size
== -1 || size
> 8);
3618 #undef TARGET_RTX_COSTS
3619 #define TARGET_RTX_COSTS rl78_rtx_costs
3621 static bool rl78_rtx_costs (rtx x
,
3623 int outer_code ATTRIBUTE_UNUSED
,
3624 int opno ATTRIBUTE_UNUSED
,
3626 bool speed ATTRIBUTE_UNUSED
)
3628 if (code
== IF_THEN_ELSE
)
3629 return COSTS_N_INSNS (10);
3630 if (GET_MODE (x
) == SImode
)
3636 *total
= COSTS_N_INSNS (14);
3637 else if (RL78_MUL_G13
)
3638 *total
= COSTS_N_INSNS (29);
3640 *total
= COSTS_N_INSNS (500);
3643 *total
= COSTS_N_INSNS (8);
3648 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3650 switch (INTVAL (XEXP (x
, 1)))
3652 case 0: *total
= COSTS_N_INSNS (0); break;
3653 case 1: *total
= COSTS_N_INSNS (6); break;
3654 case 2: case 3: case 4: case 5: case 6: case 7:
3655 *total
= COSTS_N_INSNS (10); break;
3656 case 8: *total
= COSTS_N_INSNS (6); break;
3657 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3658 *total
= COSTS_N_INSNS (10); break;
3659 case 16: *total
= COSTS_N_INSNS (3); break;
3660 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3661 *total
= COSTS_N_INSNS (4); break;
3662 case 24: *total
= COSTS_N_INSNS (4); break;
3663 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3664 *total
= COSTS_N_INSNS (5); break;
3668 *total
= COSTS_N_INSNS (10+4*16);
3676 #undef TARGET_UNWIND_WORD_MODE
3677 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3679 static enum machine_mode
3680 rl78_unwind_word_mode (void)
3685 struct gcc_target targetm
= TARGET_INITIALIZER
;
3687 #include "gt-rl78.h"