1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2014 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "stor-layout.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
35 #include "insn-attr.h"
42 #include "diagnostic-core.h"
50 #include "target-def.h"
51 #include "langhooks.h"
52 #include "rl78-protos.h"
54 #include "tree-pass.h"
56 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
57 #include "insn-flags.h" /* for gen_*(). */
60 static inline bool is_interrupt_func (const_tree decl
);
61 static inline bool is_brk_interrupt_func (const_tree decl
);
62 static void rl78_reorg (void);
65 /* Debugging statements are tagged with DEBUG0 only so that they can
66 be easily enabled individually, by replacing the '0' with '1' as
71 /* REGISTER_NAMES has the names for individual 8-bit registers, but
72 these have the names we need to use when referring to 16-bit
74 static const char * const word_regnames
[] =
76 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
78 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
79 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
80 "sp", "ap", "psw", "es", "cs"
83 struct GTY(()) machine_function
85 /* If set, the rest of the fields have been computed. */
87 /* Which register pairs need to be pushed in the prologue. */
88 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
90 /* These fields describe the frame layout... */
92 /* 4 bytes for saved PC */
96 int framesize_outgoing
;
100 /* If set, recog is allowed to match against the "real" patterns. */
102 /* If set, recog is allowed to match against the "virtual" patterns. */
104 /* Set if the current function needs to clean up any trampolines. */
105 int trampolines_used
;
108 /* This is our init_machine_status, as set in
109 rl78_option_override. */
110 static struct machine_function
*
111 rl78_init_machine_status (void)
113 struct machine_function
*m
;
115 m
= ggc_cleared_alloc
<machine_function
> ();
116 m
->virt_insns_ok
= 1;
121 /* This pass converts virtual instructions using virtual registers, to
122 real instructions using real registers. Rather than run it as
123 reorg, we reschedule it before vartrack to help with debugging. */
126 const pass_data pass_data_rl78_devirt
=
130 OPTGROUP_NONE
, /* optinfo_flags */
131 true, /* has_execute */
132 TV_MACH_DEP
, /* tv_id */
133 0, /* properties_required */
134 0, /* properties_provided */
135 0, /* properties_destroyed */
136 0, /* todo_flags_start */
137 0, /* todo_flags_finish */
140 class pass_rl78_devirt
: public rtl_opt_pass
143 pass_rl78_devirt(gcc::context
*ctxt
)
144 : rtl_opt_pass(pass_data_rl78_devirt
, ctxt
)
148 /* opt_pass methods: */
149 virtual unsigned int execute (function
*)
160 make_pass_rl78_devirt (gcc::context
*ctxt
)
162 return new pass_rl78_devirt (ctxt
);
165 /* Redundant move elimination pass. Must be run after the basic block
166 reordering pass for the best effect. */
169 move_elim_pass (void)
171 rtx insn
, ninsn
, prev
= NULL_RTX
;
173 for (insn
= get_insns (); insn
; insn
= ninsn
)
177 ninsn
= next_nonnote_nondebug_insn (insn
);
179 if ((set
= single_set (insn
)) == NULL_RTX
)
185 /* If we have two SET insns in a row (without anything
186 between them) and the source of the second one is the
187 destination of the first one, and vice versa, then we
188 can eliminate the second SET. */
190 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
191 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
195 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
206 print_rtl_with_bb (dump_file
, get_insns (), 0);
213 const pass_data pass_data_rl78_move_elim
=
216 "move_elim", /* name */
217 OPTGROUP_NONE
, /* optinfo_flags */
218 true, /* has_execute */
219 TV_MACH_DEP
, /* tv_id */
220 0, /* properties_required */
221 0, /* properties_provided */
222 0, /* properties_destroyed */
223 0, /* todo_flags_start */
224 0, /* todo_flags_finish */
227 class pass_rl78_move_elim
: public rtl_opt_pass
230 pass_rl78_move_elim(gcc::context
*ctxt
)
231 : rtl_opt_pass(pass_data_rl78_move_elim
, ctxt
)
235 /* opt_pass methods: */
236 virtual unsigned int execute (function
*) { return move_elim_pass (); }
242 make_pass_rl78_move_elim (gcc::context
*ctxt
)
244 return new pass_rl78_move_elim (ctxt
);
247 #undef TARGET_ASM_FILE_START
248 #define TARGET_ASM_FILE_START rl78_asm_file_start
251 rl78_asm_file_start (void)
257 /* The memory used is 0xffec8 to 0xffedf; real registers are in
258 0xffee0 to 0xffee7. */
259 for (i
= 8; i
< 32; i
++)
260 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
264 for (i
= 0; i
< 8; i
++)
266 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
267 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
268 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
272 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
273 static struct register_pass_info rl78_devirt_info
=
278 PASS_POS_INSERT_BEFORE
281 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
282 static struct register_pass_info rl78_move_elim_info
=
287 PASS_POS_INSERT_AFTER
290 register_pass (& rl78_devirt_info
);
291 register_pass (& rl78_move_elim_info
);
295 #undef TARGET_OPTION_OVERRIDE
296 #define TARGET_OPTION_OVERRIDE rl78_option_override
299 rl78_option_override (void)
301 flag_omit_frame_pointer
= 1;
302 flag_no_function_cse
= 1;
303 flag_split_wide_types
= 0;
305 init_machine_status
= rl78_init_machine_status
;
311 for (i
= 24; i
< 32; i
++)
316 /* Most registers are 8 bits. Some are 16 bits because, for example,
317 gcc doesn't like dealing with $FP as a register pair (the second
318 half of $fp is also 2 to keep reload happy wrt register pairs, but
319 no register class includes it). This table maps register numbers
321 static const int register_sizes
[] =
323 1, 1, 1, 1, 1, 1, 1, 1,
324 1, 1, 1, 1, 1, 1, 1, 1,
325 1, 1, 1, 1, 1, 1, 2, 2,
326 1, 1, 1, 1, 1, 1, 1, 1,
330 /* Predicates used in the MD patterns. This one is true when virtual
331 insns may be matched, which typically means before (or during) the
334 rl78_virt_insns_ok (void)
337 return cfun
->machine
->virt_insns_ok
;
341 /* Predicates used in the MD patterns. This one is true when real
342 insns may be matched, which typically means after (or during) the
345 rl78_real_insns_ok (void)
348 return cfun
->machine
->real_insns_ok
;
352 /* Implements HARD_REGNO_NREGS. */
354 rl78_hard_regno_nregs (int regno
, enum machine_mode mode
)
356 int rs
= register_sizes
[regno
];
359 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
362 /* Implements HARD_REGNO_MODE_OK. */
364 rl78_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
366 int s
= GET_MODE_SIZE (mode
);
370 /* These are not to be used by gcc. */
371 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
373 /* $fp can always be accessed as a 16-bit value. */
374 if (regno
== FP_REG
&& s
== 2)
378 /* Since a reg-reg move is really a reg-mem move, we must
379 enforce alignment. */
380 if (s
> 1 && (regno
% 2))
385 return (mode
== BImode
);
386 /* All other registers must be accessed in their natural sizes. */
387 if (s
== register_sizes
[regno
])
392 /* Simplify_gen_subreg() doesn't handle memory references the way we
393 need it to below, so we use this function for when we must get a
394 valid subreg in a "natural" state. */
396 rl78_subreg (enum machine_mode mode
, rtx r
, enum machine_mode omode
, int byte
)
398 if (GET_CODE (r
) == MEM
)
399 return adjust_address (r
, mode
, byte
);
401 return simplify_gen_subreg (mode
, r
, omode
, byte
);
404 /* Used by movsi. Split SImode moves into two HImode moves, using
405 appropriate patterns for the upper and lower halves of symbols. */
407 rl78_expand_movsi (rtx
*operands
)
409 rtx op00
, op02
, op10
, op12
;
411 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
412 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
413 if (GET_CODE (operands
[1]) == CONST
414 || GET_CODE (operands
[1]) == SYMBOL_REF
)
416 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
417 op10
= gen_rtx_CONST (HImode
, op10
);
418 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
419 op12
= gen_rtx_CONST (HImode
, op12
);
423 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
424 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
427 if (rtx_equal_p (operands
[0], operands
[1]))
429 else if (rtx_equal_p (op00
, op12
))
431 emit_move_insn (op02
, op12
);
432 emit_move_insn (op00
, op10
);
436 emit_move_insn (op00
, op10
);
437 emit_move_insn (op02
, op12
);
441 /* Generate code to move an SImode value. */
443 rl78_split_movsi (rtx
*operands
)
445 rtx op00
, op02
, op10
, op12
;
447 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
448 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
450 if (GET_CODE (operands
[1]) == CONST
451 || GET_CODE (operands
[1]) == SYMBOL_REF
)
453 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
454 op10
= gen_rtx_CONST (HImode
, op10
);
455 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
456 op12
= gen_rtx_CONST (HImode
, op12
);
460 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
461 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
464 if (rtx_equal_p (operands
[0], operands
[1]))
466 else if (rtx_equal_p (op00
, op12
))
482 /* Used by various two-operand expanders which cannot accept all
483 operands in the "far" namespace. Force some such operands into
484 registers so that each pattern has at most one far operand. */
486 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
491 /* FIXME: in the future, be smarter about only doing this if the
492 other operand is also far, assuming the devirtualizer can also
494 if (rl78_far_p (operands
[0]))
496 temp_reg
= operands
[0];
497 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
503 emit_insn (gen (operands
[0], operands
[1]));
505 emit_move_insn (temp_reg
, operands
[0]);
509 /* Likewise, but for three-operand expanders. */
511 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
516 /* FIXME: Likewise. */
517 if (rl78_far_p (operands
[1]))
519 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
520 emit_move_insn (temp_reg
, operands
[1]);
521 operands
[1] = temp_reg
;
524 if (rl78_far_p (operands
[0]))
526 temp_reg
= operands
[0];
527 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
533 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
535 emit_move_insn (temp_reg
, operands
[0]);
539 #undef TARGET_CAN_ELIMINATE
540 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
543 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
548 /* Returns true if the given register needs to be saved by the
551 need_to_save (unsigned int regno
)
553 if (is_interrupt_func (cfun
->decl
))
555 /* We don't know what devirt will need */
559 /* We don't need to save registers that have
560 been reserved for interrupt handlers. */
564 /* If the handler is a non-leaf function then it may call
565 non-interrupt aware routines which will happily clobber
566 any call_used registers, so we have to preserve them. */
567 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
570 /* Otherwise we only have to save a register, call_used
571 or not, if it is used by this handler. */
572 return df_regs_ever_live_p (regno
);
575 if (regno
== FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
577 if (fixed_regs
[regno
])
579 if (crtl
->calls_eh_return
)
581 if (df_regs_ever_live_p (regno
)
582 && !call_used_regs
[regno
])
587 /* We use this to wrap all emitted insns in the prologue. */
591 RTX_FRAME_RELATED_P (x
) = 1;
595 /* Compute all the frame-related fields in our machine_function
598 rl78_compute_frame_info (void)
602 cfun
->machine
->computed
= 1;
603 cfun
->machine
->framesize_regs
= 0;
604 cfun
->machine
->framesize_locals
= get_frame_size ();
605 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
607 for (i
= 0; i
< 16; i
++)
608 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
610 cfun
->machine
->need_to_push
[i
] = 1;
611 cfun
->machine
->framesize_regs
+= 2;
614 cfun
->machine
->need_to_push
[i
] = 0;
616 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
617 cfun
->machine
->framesize_locals
++;
619 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
620 + cfun
->machine
->framesize_locals
621 + cfun
->machine
->framesize_outgoing
);
624 /* Returns true if the provided function has the specified attribute. */
626 has_func_attr (const_tree decl
, const char * func_attr
)
628 if (decl
== NULL_TREE
)
629 decl
= current_function_decl
;
631 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
634 /* Returns true if the provided function has the "interrupt" attribute. */
636 is_interrupt_func (const_tree decl
)
638 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
641 /* Returns true if the provided function has the "brk_interrupt" attribute. */
643 is_brk_interrupt_func (const_tree decl
)
645 return has_func_attr (decl
, "brk_interrupt");
648 /* Check "interrupt" attributes. */
650 rl78_handle_func_attribute (tree
* node
,
653 int flags ATTRIBUTE_UNUSED
,
656 gcc_assert (DECL_P (* node
));
657 gcc_assert (args
== NULL_TREE
);
659 if (TREE_CODE (* node
) != FUNCTION_DECL
)
661 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
663 * no_add_attrs
= true;
666 /* FIXME: We ought to check that the interrupt and exception
667 handler attributes have been applied to void functions. */
671 #undef TARGET_ATTRIBUTE_TABLE
672 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
674 /* Table of RL78-specific attributes. */
675 const struct attribute_spec rl78_attribute_table
[] =
677 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
678 affects_type_identity. */
679 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
681 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
683 { "naked", 0, 0, true, false, false, rl78_handle_func_attribute
,
685 { NULL
, 0, 0, false, false, false, NULL
, false }
690 /* Break down an address RTX into its component base/index/addend
691 portions and return TRUE if the address is of a valid form, else
694 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
700 if (GET_CODE (x
) == UNSPEC
701 && XINT (x
, 1) == UNS_ES_ADDR
)
702 x
= XVECEXP (x
, 0, 1);
704 if (GET_CODE (x
) == REG
)
710 /* We sometimes get these without the CONST wrapper */
711 if (GET_CODE (x
) == PLUS
712 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
713 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
719 if (GET_CODE (x
) == PLUS
)
724 if (GET_CODE (*base
) != REG
725 && GET_CODE (x
) == REG
)
732 if (GET_CODE (*base
) != REG
)
735 if (GET_CODE (x
) == ZERO_EXTEND
736 && GET_CODE (XEXP (x
, 0)) == REG
)
738 *index
= XEXP (x
, 0);
743 switch (GET_CODE (x
))
746 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
747 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
770 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
773 rl78_hl_b_c_addr_p (rtx op
)
777 if (GET_CODE (op
) != PLUS
)
781 if (GET_CODE (hl
) == ZERO_EXTEND
)
787 if (GET_CODE (hl
) != REG
)
789 if (GET_CODE (bc
) != ZERO_EXTEND
)
792 if (GET_CODE (bc
) != REG
)
794 if (REGNO (hl
) != HL_REG
)
796 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
802 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
804 /* Used in various constraints and predicates to match operands in the
805 "far" address space. */
812 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx (x
);
813 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
815 return MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
;
818 /* Return the appropriate mode for a named address pointer. */
819 #undef TARGET_ADDR_SPACE_POINTER_MODE
820 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
821 static enum machine_mode
822 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
826 case ADDR_SPACE_GENERIC
:
835 /* Returns TRUE for valid addresses. */
836 #undef TARGET_VALID_POINTER_MODE
837 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
839 rl78_valid_pointer_mode (enum machine_mode m
)
841 return (m
== HImode
|| m
== SImode
);
844 /* Return the appropriate mode for a named address address. */
845 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
846 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
847 static enum machine_mode
848 rl78_addr_space_address_mode (addr_space_t addrspace
)
852 case ADDR_SPACE_GENERIC
:
861 #undef TARGET_LEGITIMATE_CONSTANT_P
862 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
865 rl78_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
870 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
871 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
874 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
875 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
877 rtx base
, index
, addend
;
878 bool is_far_addr
= false;
880 if (GET_CODE (x
) == UNSPEC
881 && XINT (x
, 1) == UNS_ES_ADDR
)
883 x
= XVECEXP (x
, 0, 1);
887 if (as
== ADDR_SPACE_GENERIC
888 && (GET_MODE (x
) == SImode
|| is_far_addr
))
891 if (! characterize_address (x
, &base
, &index
, &addend
))
894 /* We can't extract the high/low portions of a PLUS address
895 involving a register during devirtualization, so make sure all
896 such __far addresses do not have addends. This forces GCC to do
897 the sum separately. */
898 if (addend
&& base
&& as
== ADDR_SPACE_FAR
)
903 int ir
= REGNO (index
);
904 int br
= REGNO (base
);
906 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
907 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
908 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
912 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
915 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
916 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
922 /* Determine if one named address space is a subset of another. */
923 #undef TARGET_ADDR_SPACE_SUBSET_P
924 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
926 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
928 gcc_assert (subset
== ADDR_SPACE_GENERIC
|| subset
== ADDR_SPACE_FAR
);
929 gcc_assert (superset
== ADDR_SPACE_GENERIC
|| superset
== ADDR_SPACE_FAR
);
931 if (subset
== superset
)
935 return (subset
== ADDR_SPACE_GENERIC
&& superset
== ADDR_SPACE_FAR
);
938 #undef TARGET_ADDR_SPACE_CONVERT
939 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
940 /* Convert from one address space to another. */
942 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
944 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
945 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
948 gcc_assert (from_as
== ADDR_SPACE_GENERIC
|| from_as
== ADDR_SPACE_FAR
);
949 gcc_assert (to_as
== ADDR_SPACE_GENERIC
|| to_as
== ADDR_SPACE_FAR
);
951 if (to_as
== ADDR_SPACE_GENERIC
&& from_as
== ADDR_SPACE_FAR
)
953 /* This is unpredictable, as we're truncating off usable address
956 result
= gen_reg_rtx (HImode
);
957 emit_move_insn (result
, simplify_subreg (HImode
, op
, SImode
, 0));
960 else if (to_as
== ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_GENERIC
)
962 /* This always works. */
963 result
= gen_reg_rtx (SImode
);
964 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
965 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
972 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
974 rl78_regno_mode_code_ok_for_base_p (int regno
, enum machine_mode mode ATTRIBUTE_UNUSED
,
975 addr_space_t address_space ATTRIBUTE_UNUSED
,
976 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
978 if (regno
<= SP_REG
&& regno
>= 16)
980 if (index_code
== REG
)
981 return (regno
== HL_REG
);
982 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
987 /* Implements MODE_CODE_BASE_REG_CLASS. */
989 rl78_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED
,
990 addr_space_t address_space ATTRIBUTE_UNUSED
,
991 int outer_code ATTRIBUTE_UNUSED
,
992 int index_code ATTRIBUTE_UNUSED
)
997 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
998 described in the machine_Function struct definition, above. */
1000 rl78_initial_elimination_offset (int from
, int to
)
1002 int rv
= 0; /* as if arg to arg */
1004 rl78_compute_frame_info ();
1008 case STACK_POINTER_REGNUM
:
1009 rv
+= cfun
->machine
->framesize_outgoing
;
1010 rv
+= cfun
->machine
->framesize_locals
;
1012 case FRAME_POINTER_REGNUM
:
1013 rv
+= cfun
->machine
->framesize_regs
;
1022 case FRAME_POINTER_REGNUM
:
1024 rv
-= cfun
->machine
->framesize_regs
;
1025 case ARG_POINTER_REGNUM
:
1035 rl78_is_naked_func (void)
1037 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1040 /* Expand the function prologue (from the prologue pattern). */
1042 rl78_expand_prologue (void)
1045 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1048 if (rl78_is_naked_func ())
1051 /* Always re-compute the frame info - the register usage may have changed. */
1052 rl78_compute_frame_info ();
1054 if (flag_stack_usage_info
)
1055 current_function_static_stack_size
= cfun
->machine
->framesize
;
1057 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1058 for (i
= 0; i
< 4; i
++)
1059 if (cfun
->machine
->need_to_push
[i
])
1061 /* Select Bank 0 if we are using any registers from Bank 0. */
1062 emit_insn (gen_sel_rb (GEN_INT (0)));
1066 for (i
= 0; i
< 16; i
++)
1067 if (cfun
->machine
->need_to_push
[i
])
1071 emit_move_insn (gen_rtx_REG (HImode
, 0), gen_rtx_REG (HImode
, i
*2));
1072 F (emit_insn (gen_push (gen_rtx_REG (HImode
, 0))));
1076 int need_bank
= i
/4;
1078 if (need_bank
!= rb
)
1080 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1083 F (emit_insn (gen_push (gen_rtx_REG (HImode
, i
*2))));
1088 emit_insn (gen_sel_rb (GEN_INT (0)));
1090 if (frame_pointer_needed
)
1092 F (emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1093 gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
)));
1094 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
),
1095 gen_rtx_REG (HImode
, AX_REG
)));
1098 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1101 int fs_byte
= (fs
> 254) ? 254 : fs
;
1102 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1107 /* Expand the function epilogue (from the epilogue pattern). */
1109 rl78_expand_epilogue (void)
1112 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1115 if (rl78_is_naked_func ())
1118 if (frame_pointer_needed
)
1120 emit_move_insn (gen_rtx_REG (HImode
, AX_REG
),
1121 gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1122 emit_move_insn (gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
),
1123 gen_rtx_REG (HImode
, AX_REG
));
1127 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1130 int fs_byte
= (fs
> 254) ? 254 : fs
;
1132 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1137 for (i
= 15; i
>= 0; i
--)
1138 if (cfun
->machine
->need_to_push
[i
])
1142 emit_insn (gen_pop (gen_rtx_REG (HImode
, 0)));
1143 emit_move_insn (gen_rtx_REG (HImode
, i
*2), gen_rtx_REG (HImode
, 0));
1147 int need_bank
= i
/ 4;
1149 if (need_bank
!= rb
)
1151 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1154 emit_insn (gen_pop (gen_rtx_REG (HImode
, i
* 2)));
1159 emit_insn (gen_sel_rb (GEN_INT (0)));
1161 if (cfun
->machine
->trampolines_used
)
1162 emit_insn (gen_trampoline_uninit ());
1164 if (is_brk_interrupt_func (cfun
->decl
))
1165 emit_jump_insn (gen_brk_interrupt_return ());
1166 else if (is_interrupt_func (cfun
->decl
))
1167 emit_jump_insn (gen_interrupt_return ());
1169 emit_jump_insn (gen_rl78_return ());
1172 /* Likewise, for exception handlers. */
1174 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1176 /* FIXME - replace this with an indirect jump with stack adjust. */
1177 emit_jump_insn (gen_rl78_return ());
1180 #undef TARGET_ASM_FUNCTION_PROLOGUE
1181 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1183 /* We don't use this to actually emit the function prologue. We use
1184 this to insert a comment in the asm file describing the
1187 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1191 if (cfun
->machine
->framesize
== 0)
1193 fprintf (file
, "\t; start of function\n");
1195 if (cfun
->machine
->framesize_regs
)
1197 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1198 for (i
= 0; i
< 16; i
++)
1199 if (cfun
->machine
->need_to_push
[i
])
1200 fprintf (file
, " %s", word_regnames
[i
*2]);
1201 fprintf (file
, "\n");
1204 if (frame_pointer_needed
)
1205 fprintf (file
, "\t; $fp points here (r22)\n");
1207 if (cfun
->machine
->framesize_locals
)
1208 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1209 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1211 if (cfun
->machine
->framesize_outgoing
)
1212 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1213 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1216 /* Return an RTL describing where a function return value of type RET_TYPE
1219 #undef TARGET_FUNCTION_VALUE
1220 #define TARGET_FUNCTION_VALUE rl78_function_value
1223 rl78_function_value (const_tree ret_type
,
1224 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1225 bool outgoing ATTRIBUTE_UNUSED
)
1227 enum machine_mode mode
= TYPE_MODE (ret_type
);
1229 return gen_rtx_REG (mode
, 8);
1232 #undef TARGET_PROMOTE_FUNCTION_MODE
1233 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1235 static enum machine_mode
1236 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1237 enum machine_mode mode
,
1238 int *punsignedp ATTRIBUTE_UNUSED
,
1239 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1244 /* Return an RTL expression describing the register holding a function
1245 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1246 be passed on the stack. CUM describes the previous parameters to the
1247 function and NAMED is false if the parameter is part of a variable
1248 parameter list, or the last named parameter before the start of a
1249 variable parameter list. */
1251 #undef TARGET_FUNCTION_ARG
1252 #define TARGET_FUNCTION_ARG rl78_function_arg
1255 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1256 enum machine_mode mode ATTRIBUTE_UNUSED
,
1257 const_tree type ATTRIBUTE_UNUSED
,
1258 bool named ATTRIBUTE_UNUSED
)
1263 #undef TARGET_FUNCTION_ARG_ADVANCE
1264 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1267 rl78_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
, const_tree type
,
1268 bool named ATTRIBUTE_UNUSED
)
1271 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1273 rounded_size
= ((mode
== BLKmode
)
1274 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1275 if (rounded_size
& 1)
1277 (*cum
) += rounded_size
;
1280 #undef TARGET_FUNCTION_ARG_BOUNDARY
1281 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1284 rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED
,
1285 const_tree type ATTRIBUTE_UNUSED
)
1290 /* Supported modifier letters:
1292 A - address of a MEM
1293 S - SADDR form of a real register
1294 v - real register corresponding to a virtual register
1295 m - minus - negative of CONST_INT value.
1296 C - inverse of a conditional (NE vs EQ for example)
1297 C - complement of an integer
1298 z - collapsed conditional
1299 s - shift count mod 8
1300 S - shift count mod 16
1301 r - reverse shift count (8-(count mod 8))
1304 h - bottom HI of an SI
1306 q - bottom QI of an HI
1308 e - third QI of an SI (i.e. where the ES register gets values from)
1309 E - fourth QI of an SI (i.e. MSB)
1313 /* Implements the bulk of rl78_print_operand, below. We do it this
1314 way because we need to test for a constant at the top level and
1315 insert the '#', but not test for it anywhere else as we recurse
1316 down into the operand. */
1318 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1322 switch (GET_CODE (op
))
1326 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1329 if (rl78_far_p (op
))
1331 fprintf (file
, "es:");
1332 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1336 op
= adjust_address (op
, HImode
, 2);
1341 op
= adjust_address (op
, HImode
, 0);
1346 op
= adjust_address (op
, QImode
, 1);
1351 op
= adjust_address (op
, QImode
, 0);
1356 op
= adjust_address (op
, QImode
, 2);
1361 op
= adjust_address (op
, QImode
, 3);
1364 if (CONSTANT_P (XEXP (op
, 0)))
1366 fprintf (file
, "!");
1367 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1369 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1370 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1372 fprintf (file
, "!");
1373 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1375 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1376 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1377 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1379 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1380 fprintf (file
, "[");
1381 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1382 fprintf (file
, "]");
1386 fprintf (file
, "[");
1387 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1388 fprintf (file
, "]");
1395 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1396 else if (letter
== 'H')
1397 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1398 else if (letter
== 'q')
1399 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1400 else if (letter
== 'e')
1401 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1402 else if (letter
== 'E')
1403 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1404 else if (letter
== 'S')
1405 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1406 else if (GET_MODE (op
) == HImode
1407 && ! (REGNO (op
) & ~0xfe))
1410 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1412 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1415 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1420 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1421 else if (letter
== 'H')
1422 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1423 else if (letter
== 'q')
1424 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1425 else if (letter
== 'h')
1426 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1427 else if (letter
== 'e')
1428 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1429 else if (letter
== 'B')
1430 fprintf (file
, "%d", exact_log2 (INTVAL (op
)));
1431 else if (letter
== 'E')
1432 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1433 else if (letter
== 'm')
1434 fprintf (file
, "%ld", - INTVAL (op
));
1435 else if (letter
== 's')
1436 fprintf (file
, "%ld", INTVAL (op
) % 8);
1437 else if (letter
== 'S')
1438 fprintf (file
, "%ld", INTVAL (op
) % 16);
1439 else if (letter
== 'r')
1440 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1441 else if (letter
== 'C')
1442 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1444 fprintf (file
, "%ld", INTVAL (op
));
1448 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1453 int bits
= INTVAL (XEXP (op
, 1));
1454 int ofs
= INTVAL (XEXP (op
, 2));
1455 if (bits
== 16 && ofs
== 0)
1456 fprintf (file
, "%%lo16(");
1457 else if (bits
== 16 && ofs
== 16)
1458 fprintf (file
, "%%hi16(");
1459 else if (bits
== 8 && ofs
== 16)
1460 fprintf (file
, "%%hi8(");
1463 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1464 fprintf (file
, ")");
1469 if (GET_CODE (XEXP (op
, 0)) == REG
)
1470 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1472 print_rtl (file
, op
);
1479 fprintf (file
, "%%hi16(");
1485 fprintf (file
, "%%lo16(");
1491 fprintf (file
, "%%hi8(");
1495 if (letter
== 'q' || letter
== 'Q')
1496 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1498 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1500 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1501 fprintf (file
, "+");
1502 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1506 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1507 fprintf (file
, "+");
1508 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1511 fprintf (file
, ")");
1518 fprintf (file
, "%%hi16(");
1524 fprintf (file
, "%%lo16(");
1530 fprintf (file
, "%%hi8(");
1534 if (letter
== 'q' || letter
== 'Q')
1535 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1537 output_addr_const (file
, op
);
1539 fprintf (file
, ")");
1544 output_asm_label (op
);
1549 fprintf (file
, "#comparison eliminated");
1551 fprintf (file
, letter
== 'C' ? "nc" : "c");
1555 fprintf (file
, "br");
1557 fprintf (file
, letter
== 'C' ? "h" : "nh");
1561 fprintf (file
, "br");
1563 fprintf (file
, letter
== 'C' ? "c" : "nc");
1567 fprintf (file
, "#comparison eliminated");
1569 fprintf (file
, letter
== 'C' ? "nh" : "h");
1573 fprintf (file
, "br");
1575 fprintf (file
, letter
== 'C' ? "nz" : "z");
1579 fprintf (file
, "#comparison eliminated");
1581 fprintf (file
, letter
== 'C' ? "z" : "nz");
1584 /* Note: these assume appropriate adjustments were made so that
1585 unsigned comparisons, which is all this chip has, will
1589 fprintf (file
, "#comparison eliminated");
1591 fprintf (file
, letter
== 'C' ? "nc" : "c");
1595 fprintf (file
, "br");
1597 fprintf (file
, letter
== 'C' ? "h" : "nh");
1601 fprintf (file
, "br");
1603 fprintf (file
, letter
== 'C' ? "c" : "nc");
1607 fprintf (file
, "#comparison eliminated");
1609 fprintf (file
, letter
== 'C' ? "nh" : "h");
1613 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1618 #undef TARGET_PRINT_OPERAND
1619 #define TARGET_PRINT_OPERAND rl78_print_operand
1622 rl78_print_operand (FILE * file
, rtx op
, int letter
)
1624 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
1625 fprintf (file
, "#");
1626 rl78_print_operand_1 (file
, op
, letter
);
1629 #undef TARGET_TRAMPOLINE_INIT
1630 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1632 /* Note that the RL78's addressing makes it very difficult to do
1633 trampolines on the stack. So, libgcc has a small pool of
1634 trampolines from which one is allocated to this task. */
1636 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
1638 rtx mov_addr
, thunk_addr
;
1639 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
1641 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
1642 thunk_addr
= gen_reg_rtx (HImode
);
1644 function
= force_reg (HImode
, function
);
1645 static_chain
= force_reg (HImode
, static_chain
);
1647 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
1648 emit_move_insn (mov_addr
, thunk_addr
);
1650 cfun
->machine
->trampolines_used
= 1;
1653 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
1654 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
1657 rl78_trampoline_adjust_address (rtx m_tramp
)
1659 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
1663 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
1664 the "normal" compares, specifically, it only has unsigned compares,
1665 so we must synthesize the missing ones. */
1667 rl78_expand_compare (rtx
*operands
)
1669 if (GET_CODE (operands
[2]) == MEM
)
1670 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
1675 /* Define this to 1 if you are debugging the peephole optimizers. */
1676 #define DEBUG_PEEP 0
1678 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
1679 The default "word" size is a byte so we can effectively use all the
1680 registers, but we want to do 16-bit moves whenever possible. This
1681 function determines when such a move is an option. */
1683 rl78_peep_movhi_p (rtx
*operands
)
1688 /* (set (op0) (op1))
1689 (set (op2) (op3)) */
1691 if (! rl78_virt_insns_ok ())
1695 fprintf (stderr
, "\033[33m");
1696 debug_rtx (operands
[0]);
1697 debug_rtx (operands
[1]);
1698 debug_rtx (operands
[2]);
1699 debug_rtx (operands
[3]);
1700 fprintf (stderr
, "\033[0m");
1703 /* You can move a constant to memory as QImode, but not HImode. */
1704 if (GET_CODE (operands
[0]) == MEM
1705 && GET_CODE (operands
[1]) != REG
)
1708 fprintf (stderr
, "no peep: move constant to memory\n");
1713 if (rtx_equal_p (operands
[0], operands
[3]))
1716 fprintf (stderr
, "no peep: overlapping\n");
1721 for (i
= 0; i
< 2; i
++)
1723 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
1726 fprintf (stderr
, "no peep: different codes\n");
1730 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
1733 fprintf (stderr
, "no peep: different modes\n");
1738 switch (GET_CODE (operands
[i
]))
1742 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
1743 || GET_MODE (operands
[i
]) != QImode
)
1746 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
1747 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
1752 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
1755 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
1765 if (GET_MODE (operands
[i
]) != QImode
)
1767 if (MEM_ALIGN (operands
[i
]) < 16)
1769 a
= XEXP (operands
[i
], 0);
1770 if (GET_CODE (a
) == CONST
)
1772 if (GET_CODE (a
) == PLUS
)
1774 if (GET_CODE (a
) == CONST_INT
1778 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
1779 debug_rtx (operands
[i
]);
1783 m
= adjust_address (operands
[i
], QImode
, 1);
1784 if (! rtx_equal_p (m
, operands
[i
+2]))
1787 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
1789 debug_rtx (operands
[i
+2]);
1797 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
1803 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
1808 /* Likewise, when a peephole is activated, this function helps compute
1809 the new operands. */
1811 rl78_setup_peep_movhi (rtx
*operands
)
1815 for (i
= 0; i
< 2; i
++)
1817 switch (GET_CODE (operands
[i
]))
1820 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
1824 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char) INTVAL (operands
[i
+2])) * 256);
1828 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
1838 How Devirtualization works in the RL78 GCC port
1842 The RL78 is an 8-bit port with some 16-bit operations. It has 32
1843 bytes of register space, in four banks, memory-mapped. One bank is
1844 the "selected" bank and holds the registers used for primary
1845 operations. Since the registers are memory mapped, often you can
1846 still refer to the unselected banks via memory accesses.
1850 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
1851 and refers to the other banks via their memory addresses, although
1852 they're treated as regular registers internally. These "virtual"
1853 registers are R8 through R23 (bank3 is reserved for asm-based
1854 interrupt handlers).
1856 There are four machine description files:
1858 rl78.md - common register-independent patterns and definitions
1859 rl78-expand.md - expanders
1860 rl78-virt.md - patterns that match BEFORE devirtualization
1861 rl78-real.md - patterns that match AFTER devirtualization
1863 At least through register allocation and reload, gcc is told that it
1864 can do pretty much anything - but may only use the virtual registers.
1865 GCC cannot properly create the varying addressing modes that the RL78
1866 supports in an efficient way.
1868 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
1869 uses the "valloc" attribute in rl78-virt.md for determining the rules
1870 by which it will replace virtual registers with real registers (or
1871 not) and how to make up addressing modes. For example, insns tagged
1872 with "ro1" have a single read-only parameter, which may need to be
1873 moved from memory/constant/vreg to a suitable real register. As part
1874 of devirtualization, a flag is toggled, disabling the rl78-virt.md
1875 patterns and enabling the rl78-real.md patterns. The new patterns'
1876 constraints are used to determine the real registers used. NOTE:
1877 patterns in rl78-virt.md essentially ignore the constrains and rely on
1878 predicates, where the rl78-real.md ones essentially ignore the
1879 predicates and rely on the constraints.
1881 The devirtualization pass is scheduled via the pass manager (despite
1882 being called "rl78_reorg") so it can be scheduled prior to var-track
1883 (the idea is to let gdb know about the new registers). Ideally, it
1884 would be scheduled right after pro/epilogue generation, so the
1885 post-reload optimizers could operate on the real registers, but when I
1886 tried that there were some issues building the target libraries.
1888 During devirtualization, a simple register move optimizer is run. It
1889 would be better to run a full CSE/propogation pass on it though, but
1890 that has not yet been attempted.
1893 #define DEBUG_ALLOC 0
1895 #define OP(x) (*recog_data.operand_loc[x])
1897 /* This array is used to hold knowledge about the contents of the
1898 real registers (A ... H), the memory-based registers (r8 ... r31)
1899 and the first NUM_STACK_LOCS words on the stack. We use this to
1900 avoid generating redundant move instructions.
1902 A value in the range 0 .. 31 indicates register A .. r31.
1903 A value in the range 32 .. 63 indicates stack slot (value - 32).
1904 A value of NOT_KNOWN indicates that the contents of that location
1907 #define NUM_STACK_LOCS 32
1908 #define NOT_KNOWN 127
1910 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
1912 static unsigned char saved_update_index
= NOT_KNOWN
;
1913 static unsigned char saved_update_value
;
1914 static enum machine_mode saved_update_mode
;
1918 clear_content_memory (void)
1920 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
1922 fprintf (dump_file
, " clear content memory\n");
1923 saved_update_index
= NOT_KNOWN
;
1926 /* Convert LOC into an index into the content_memory array.
1927 If LOC cannot be converted, return NOT_KNOWN. */
1929 static unsigned char
1930 get_content_index (rtx loc
)
1932 enum machine_mode mode
;
1934 if (loc
== NULL_RTX
)
1939 if (REGNO (loc
) < 32)
1944 mode
= GET_MODE (loc
);
1946 if (! rl78_stack_based_mem (loc
, mode
))
1949 loc
= XEXP (loc
, 0);
1952 /* loc = MEM (SP) */
1955 /* loc = MEM (PLUS (SP, INT)). */
1956 loc
= XEXP (loc
, 1);
1958 if (INTVAL (loc
) < NUM_STACK_LOCS
)
1959 return 32 + INTVAL (loc
);
1964 /* Return a string describing content INDEX in mode MODE.
1965 WARNING: Can return a pointer to a static buffer. */
1967 get_content_name (unsigned char index
, enum machine_mode mode
)
1969 static char buffer
[128];
1971 if (index
== NOT_KNOWN
)
1975 sprintf (buffer
, "stack slot %d", index
- 32);
1976 else if (mode
== HImode
)
1977 sprintf (buffer
, "%s%s",
1978 reg_names
[index
+ 1], reg_names
[index
]);
1980 return reg_names
[index
];
1988 display_content_memory (FILE * file
)
1992 fprintf (file
, " Known memory contents:\n");
1994 for (i
= 0; i
< sizeof content_memory
; i
++)
1995 if (content_memory
[i
] != NOT_KNOWN
)
1997 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
1998 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2004 update_content (unsigned char index
, unsigned char val
, enum machine_mode mode
)
2008 gcc_assert (index
< sizeof content_memory
);
2010 content_memory
[index
] = val
;
2011 if (val
!= NOT_KNOWN
)
2012 content_memory
[val
] = index
;
2014 /* Make the entry in dump_file *before* VAL is increased below. */
2017 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2018 if (val
== NOT_KNOWN
)
2019 fprintf (dump_file
, "Unknown\n");
2021 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2026 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2028 content_memory
[index
+ 1] = val
;
2029 if (val
!= NOT_KNOWN
)
2031 content_memory
[val
] = index
+ 1;
2036 /* Any other places that had INDEX recorded as their contents are now invalid. */
2037 for (i
= 0; i
< sizeof content_memory
; i
++)
2040 || (val
!= NOT_KNOWN
&& i
== val
))
2047 if (content_memory
[i
] == index
2048 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2050 content_memory
[i
] = NOT_KNOWN
;
2053 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2056 content_memory
[++ i
] = NOT_KNOWN
;
2061 /* Record that LOC contains VALUE.
2062 For HImode locations record that LOC+1 contains VALUE+1.
2063 If LOC is not a register or stack slot, do nothing.
2064 If VALUE is not a register or stack slot, clear the recorded content. */
2067 record_content (rtx loc
, rtx value
)
2069 enum machine_mode mode
;
2070 unsigned char index
;
2073 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2076 val
= get_content_index (value
);
2078 mode
= GET_MODE (loc
);
2085 /* This should not happen when optimizing. */
2087 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2088 get_content_name (val
, mode
));
2095 update_content (index
, val
, mode
);
2098 /* Returns TRUE if LOC already contains a copy of VALUE. */
2101 already_contains (rtx loc
, rtx value
)
2103 unsigned char index
;
2106 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2109 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2112 if (content_memory
[index
] != val
)
2115 if (GET_MODE (loc
) == HImode
)
2116 return content_memory
[index
+ 1] == val
+ 1;
2122 rl78_es_addr (rtx addr
)
2124 if (GET_CODE (addr
) == MEM
)
2125 addr
= XEXP (addr
, 0);
2126 if (GET_CODE (addr
) != UNSPEC
)
2128 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2134 rl78_es_base (rtx addr
)
2136 if (GET_CODE (addr
) == MEM
)
2137 addr
= XEXP (addr
, 0);
2138 addr
= XVECEXP (addr
, 0, 1);
2139 if (GET_CODE (addr
) == CONST
2140 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2141 addr
= XEXP (XEXP (addr
, 0), 0);
2142 /* Mode doesn't matter here. */
2143 return gen_rtx_MEM (HImode
, addr
);
2146 /* Rescans an insn to see if it's recognized again. This is done
2147 carefully to ensure that all the constraint information is accurate
2148 for the newly matched insn. */
2150 insn_ok_now (rtx insn
)
2152 rtx pattern
= PATTERN (insn
);
2155 INSN_CODE (insn
) = -1;
2157 if (recog (pattern
, insn
, 0) > -1)
2159 extract_insn (insn
);
2160 if (constrain_operands (1))
2163 fprintf (stderr
, "\033[32m");
2165 fprintf (stderr
, "\033[0m");
2167 if (SET_P (pattern
))
2168 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2170 /* We need to detect far addresses that haven't been
2171 converted to es/lo16 format. */
2172 for (i
=0; i
<recog_data
.n_operands
; i
++)
2173 if (GET_CODE (OP (i
)) == MEM
2174 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2175 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2183 /* We need to re-recog the insn with virtual registers to get
2185 cfun
->machine
->virt_insns_ok
= 1;
2186 if (recog (pattern
, insn
, 0) > -1)
2188 extract_insn (insn
);
2189 if (constrain_operands (0))
2191 cfun
->machine
->virt_insns_ok
= 0;
2197 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2204 fprintf (stderr
, "\033[31m");
2206 fprintf (stderr
, "\033[0m");
2212 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2213 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2214 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable()
2215 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2216 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2218 #define FAILED gcc_unreachable ()
2219 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2220 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2223 /* Registers into which we move the contents of virtual registers. */
2224 #define X gen_rtx_REG (QImode, X_REG)
2225 #define A gen_rtx_REG (QImode, A_REG)
2226 #define C gen_rtx_REG (QImode, C_REG)
2227 #define B gen_rtx_REG (QImode, B_REG)
2228 #define E gen_rtx_REG (QImode, E_REG)
2229 #define D gen_rtx_REG (QImode, D_REG)
2230 #define L gen_rtx_REG (QImode, L_REG)
2231 #define H gen_rtx_REG (QImode, H_REG)
2233 #define AX gen_rtx_REG (HImode, AX_REG)
2234 #define BC gen_rtx_REG (HImode, BC_REG)
2235 #define DE gen_rtx_REG (HImode, DE_REG)
2236 #define HL gen_rtx_REG (HImode, HL_REG)
2238 /* Returns TRUE if R is a virtual register. */
2240 is_virtual_register (rtx r
)
2242 return (GET_CODE (r
) == REG
2247 /* In all these alloc routines, we expect the following: the insn
2248 pattern is unshared, the insn was previously recognized and failed
2249 due to predicates or constraints, and the operand data is in
2252 static int virt_insn_was_frame
;
2254 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2257 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2260 fprintf (stderr
, "\033[36m%d: ", line
);
2262 fprintf (stderr
, "\033[0m");
2264 /*SCHED_GROUP_P (r) = 1;*/
2265 if (virt_insn_was_frame
)
2266 RTX_FRAME_RELATED_P (r
) = 1;
2270 #define EM(x) EM2 (__LINE__, x)
2272 /* Return a suitable RTX for the low half of a __far address. */
2274 rl78_lo16 (rtx addr
)
2278 if (GET_CODE (addr
) == SYMBOL_REF
2279 || GET_CODE (addr
) == CONST
)
2281 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2282 r
= gen_rtx_CONST (HImode
, r
);
2285 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2287 r
= gen_es_addr (r
);
2292 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2296 if (GET_CODE (addr
) == SYMBOL_REF
2297 || GET_CODE (addr
) == CONST
)
2299 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2300 r
= gen_rtx_CONST (QImode
, r
);
2303 return rl78_subreg (QImode
, addr
, SImode
, 2);
2307 add_postponed_content_update (rtx to
, rtx value
)
2309 unsigned char index
;
2311 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2314 gcc_assert (saved_update_index
== NOT_KNOWN
);
2315 saved_update_index
= index
;
2316 saved_update_value
= get_content_index (value
);
2317 saved_update_mode
= GET_MODE (to
);
2321 process_postponed_content_update (void)
2323 if (saved_update_index
!= NOT_KNOWN
)
2325 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2326 saved_update_index
= NOT_KNOWN
;
2330 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2331 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2332 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2333 BEFORE is true, FROM otherwise. */
2335 gen_and_emit_move (rtx to
, rtx from
, rtx where
, bool before
)
2337 enum machine_mode mode
= GET_MODE (to
);
2339 if (optimize
&& before
&& already_contains (to
, from
))
2342 display_content_memory (stderr
);
2346 fprintf (dump_file
, " Omit move of %s into ",
2347 get_content_name (get_content_index (from
), mode
));
2348 fprintf (dump_file
, "%s as it already contains this value\n",
2349 get_content_name (get_content_index (to
), mode
));
2354 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2358 if (where
== NULL_RTX
)
2361 emit_insn_before (move
, where
);
2364 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2366 /* If necessary move REG_EH_REGION notes forward.
2367 cf. compiling gcc.dg/pr44545.c. */
2368 if (note
!= NULL_RTX
)
2370 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2371 remove_note (where
, note
);
2374 emit_insn_after (move
, where
);
2378 record_content (to
, from
);
2380 add_postponed_content_update (to
, from
);
2383 return before
? to
: from
;
2386 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2387 copy it into NEWBASE and return the updated MEM. Otherwise just
2388 return M. Any needed insns are emitted before BEFORE. */
2390 transcode_memory_rtx (rtx m
, rtx newbase
, rtx before
)
2392 rtx base
, index
, addendr
;
2399 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2402 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2405 fprintf (stderr
, "setting ES:\n");
2408 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2409 emit_insn_before (EM (gen_movqi_es (A
)), before
);
2410 record_content (A
, NULL_RTX
);
2412 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2413 MEM_COPY_ATTRIBUTES (new_m
, m
);
2418 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2419 gcc_assert (index
== NULL_RTX
);
2422 fprintf (stderr
, "\033[33m"); debug_rtx (m
); fprintf (stderr
, "\033[0m");
2425 if (base
== NULL_RTX
)
2428 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2429 addend
= INTVAL (addendr
);
2431 gcc_assert (REG_P (base
));
2432 gcc_assert (REG_P (newbase
));
2434 if (REGNO (base
) == SP_REG
)
2436 if (addend
>= 0 && addend
<= 255)
2440 /* BASE should be a virtual register. We copy it to NEWBASE. If
2441 the addend is out of range for DE/HL, we use AX to compute the full
2445 || (addend
> 255 && REGNO (newbase
) != 2)
2446 || (addendr
&& GET_CODE (addendr
) != CONST_INT
))
2451 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2452 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2453 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2454 record_content (AX
, NULL_RTX
);
2455 record_content (newbase
, NULL_RTX
);
2462 base
= gen_and_emit_move (newbase
, base
, before
, true);
2467 record_content (base
, NULL_RTX
);
2468 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2472 fprintf (stderr
, "\033[33m");
2476 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2478 m
= change_address (m
, GET_MODE (m
), base
);
2481 fprintf (stderr
, "\033[0m");
2486 /* Copy SRC to accumulator (A or AX), placing any generated insns
2487 before BEFORE. Returns accumulator RTX. */
2489 move_to_acc (int opno
, rtx before
)
2491 rtx src
= OP (opno
);
2492 enum machine_mode mode
= GET_MODE (src
);
2494 if (REG_P (src
) && REGNO (src
) < 2)
2497 if (mode
== VOIDmode
)
2498 mode
= recog_data
.operand_mode
[opno
];
2500 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2504 force_into_acc (rtx src
, rtx before
)
2506 enum machine_mode mode
= GET_MODE (src
);
2509 if (REG_P (src
) && REGNO (src
) < 2)
2512 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2516 emit_insn_before (move
, before
);
2517 record_content (AX
, NULL_RTX
);
2520 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2521 after AFTER. Returns accumulator RTX. */
2523 move_from_acc (unsigned int opno
, rtx after
)
2525 rtx dest
= OP (opno
);
2526 enum machine_mode mode
= GET_MODE (dest
);
2528 if (REG_P (dest
) && REGNO (dest
) < 2)
2531 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2534 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2535 before BEFORE. Returns reg RTX. */
2537 move_acc_to_reg (rtx acc
, int regno
, rtx before
)
2539 enum machine_mode mode
= GET_MODE (acc
);
2542 reg
= gen_rtx_REG (mode
, regno
);
2544 return gen_and_emit_move (reg
, acc
, before
, true);
2547 /* Copy SRC to X, placing any generated insns before BEFORE.
2550 move_to_x (int opno
, rtx before
)
2552 rtx src
= OP (opno
);
2553 enum machine_mode mode
= GET_MODE (src
);
2556 if (mode
== VOIDmode
)
2557 mode
= recog_data
.operand_mode
[opno
];
2558 reg
= (mode
== QImode
) ? X
: AX
;
2560 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2562 OP (opno
) = move_to_acc (opno
, before
);
2563 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
2567 return gen_and_emit_move (reg
, src
, before
, true);
2570 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2571 Returns H/HL RTX. */
2573 move_to_hl (int opno
, rtx before
)
2575 rtx src
= OP (opno
);
2576 enum machine_mode mode
= GET_MODE (src
);
2579 if (mode
== VOIDmode
)
2580 mode
= recog_data
.operand_mode
[opno
];
2581 reg
= (mode
== QImode
) ? L
: HL
;
2583 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2585 OP (opno
) = move_to_acc (opno
, before
);
2586 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
2590 return gen_and_emit_move (reg
, src
, before
, true);
2593 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2594 Returns E/DE RTX. */
2596 move_to_de (int opno
, rtx before
)
2598 rtx src
= OP (opno
);
2599 enum machine_mode mode
= GET_MODE (src
);
2602 if (mode
== VOIDmode
)
2603 mode
= recog_data
.operand_mode
[opno
];
2605 reg
= (mode
== QImode
) ? E
: DE
;
2607 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2609 OP (opno
) = move_to_acc (opno
, before
);
2610 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
2614 gen_and_emit_move (reg
, src
, before
, true);
2620 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2622 rl78_alloc_physical_registers_op1 (rtx insn
)
2624 /* op[0] = func op[1] */
2626 /* We first try using A as the destination, then copying it
2628 if (rtx_equal_p (OP (0), OP (1)))
2631 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2635 /* If necessary, load the operands into BC and HL.
2636 Check to see if we already have OP (0) in HL
2637 and if so, swap the order. */
2639 && already_contains (HL
, XEXP (OP (0), 0)))
2641 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
2642 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
2646 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2647 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
2653 OP (0) = move_from_acc (0, insn
);
2657 /* Try copying the src to acc first, then. This is for, for
2658 example, ZERO_EXTEND or NOT. */
2659 OP (1) = move_to_acc (1, insn
);
2664 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
2665 Assumes that the current insn has already been recognised and hence the
2666 constraint data has been filled in. */
2668 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
2670 const char * p
= recog_data
.constraints
[opnum
];
2672 /* No constraints means anything is accepted. */
2673 if (p
== NULL
|| *p
== 0 || *p
== ',')
2682 len
= CONSTRAINT_LEN (c
, p
);
2683 gcc_assert (len
> 0);
2691 if (lookup_constraint (p
) == constraint
)
2699 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
2701 rl78_alloc_physical_registers_op2 (rtx insn
)
2709 if (rtx_equal_p (OP (0), OP (1)))
2712 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2713 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2715 else if (rtx_equal_p (OP (0), OP (2)))
2717 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2719 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2723 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2724 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2725 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2730 prev
= prev_nonnote_nondebug_insn (insn
);
2731 if (recog_data
.constraints
[1][0] == '%'
2732 && is_virtual_register (OP (1))
2733 && ! is_virtual_register (OP (2))
2734 && ! CONSTANT_P (OP (2)))
2741 /* Make a note of whether (H)L is being used. It matters
2742 because if OP (2) also needs reloading, then we must take
2743 care not to corrupt HL. */
2744 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
2746 /* If HL is not currently being used and dest == op1 then there are
2747 some possible optimizations available by reloading one of the
2748 operands into HL, before trying to use the accumulator. */
2751 && rtx_equal_p (OP (0), OP (1)))
2753 /* If op0 is a Ws1 type memory address then switching the base
2754 address register to HL might allow us to perform an in-memory
2755 operation. (eg for the INCW instruction).
2757 FIXME: Adding the move into HL is costly if this optimization is not
2758 going to work, so for now, make sure that we know that the new insn will
2759 match the requirements of the addhi3_real pattern. Really we ought to
2760 generate a candidate sequence, test that, and then install it if the
2761 results are good. */
2762 if (satisfies_constraint_Ws1 (OP (0))
2763 && has_constraint (0, CONSTRAINT_Wh1
)
2764 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
2766 rtx base
, index
, addend
, newbase
;
2768 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
2769 gcc_assert (index
== NULL_RTX
);
2770 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2772 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2773 if (addend
!= NULL_RTX
)
2775 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
2776 record_content (newbase
, NULL_RTX
);
2777 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
2779 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
2781 /* We do not want to fail here as this means that
2782 we have inserted useless insns into the stream. */
2786 else if (REG_P (OP (0))
2787 && satisfies_constraint_Ws1 (OP (2))
2788 && has_constraint (2, CONSTRAINT_Wh1
))
2790 rtx base
, index
, addend
, newbase
;
2792 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
2793 gcc_assert (index
== NULL_RTX
);
2794 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
2796 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
2797 if (addend
!= NULL_RTX
)
2799 gen_and_emit_move (HL
, base
, insn
, true);
2801 if (REGNO (OP (0)) != X_REG
)
2803 OP (1) = move_to_acc (1, insn
);
2804 OP (0) = move_from_acc (0, insn
);
2807 record_content (HL
, NULL_RTX
);
2808 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
2810 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
2812 /* We do not want to fail here as this means that
2813 we have inserted useless insns into the stream. */
2819 OP (0) = move_from_acc (0, insn
);
2821 tmp_id
= get_max_insn_count ();
2824 if (rtx_equal_p (OP (1), OP (2)))
2825 OP (2) = OP (1) = move_to_acc (1, insn
);
2827 OP (1) = move_to_acc (1, insn
);
2831 /* If we omitted the move of OP1 into the accumulator (because
2832 it was already there from a previous insn), then force the
2833 generation of the move instruction now. We know that we
2834 are about to emit a move into HL (or DE) via AX, and hence
2835 our optimization to remove the load of OP1 is no longer valid. */
2836 if (tmp_id
== get_max_insn_count ())
2837 force_into_acc (saved_op1
, insn
);
2839 /* We have to copy op2 to HL (or DE), but that involves AX, which
2840 already has a live value. Emit it before those insns. */
2843 first
= next_nonnote_nondebug_insn (prev
);
2845 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2848 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
2853 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
2855 rl78_alloc_physical_registers_ro1 (rtx insn
)
2857 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2861 OP (0) = move_to_acc (0, insn
);
2866 /* Devirtualize a compare insn. */
2868 rl78_alloc_physical_registers_cmp (rtx insn
)
2872 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2875 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2876 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2878 /* HI compares have to have OP (1) in AX, but QI
2879 compares do not, so it is worth checking here. */
2882 /* For an HImode compare, OP (1) must always be in AX.
2883 But if OP (1) is a REG (and not AX), then we can avoid
2884 a reload of OP (1) if we reload OP (2) into AX and invert
2887 && REGNO (OP (1)) != AX_REG
2888 && GET_MODE (OP (1)) == HImode
2891 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
2893 OP (2) = move_to_acc (2, insn
);
2895 switch (GET_CODE (cmp
))
2900 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
2901 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
2902 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
2903 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
2916 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
2917 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
2919 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
2924 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
2925 should be handled by the second alternative of the cbranchhi_real pattern. */
2926 if (rtx_equal_p (OP (1), OP (2)))
2928 OP (1) = OP (2) = BC
;
2932 tmp_id
= get_max_insn_count ();
2935 OP (1) = move_to_acc (1, insn
);
2939 /* If we omitted the move of OP1 into the accumulator (because
2940 it was already there from a previous insn), then force the
2941 generation of the move instruction now. We know that we
2942 are about to emit a move into HL via AX, and hence our
2943 optimization to remove the load of OP1 is no longer valid. */
2944 if (tmp_id
== get_max_insn_count ())
2945 force_into_acc (saved_op1
, insn
);
2947 /* We have to copy op2 to HL, but that involves the acc, which
2948 already has a live value. Emit it before those insns. */
2950 first
= next_nonnote_nondebug_insn (prev
);
2952 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
2954 OP (2) = move_to_hl (2, first
);
2959 /* Like op2, but AX = A * X. */
2961 rl78_alloc_physical_registers_umul (rtx insn
)
2963 rtx prev
= prev_nonnote_nondebug_insn (insn
);
2968 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
2969 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
2970 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
2974 if (recog_data
.constraints
[1][0] == '%'
2975 && is_virtual_register (OP (1))
2976 && !is_virtual_register (OP (2))
2977 && !CONSTANT_P (OP (2)))
2984 OP (0) = move_from_acc (0, insn
);
2986 tmp_id
= get_max_insn_count ();
2989 if (rtx_equal_p (OP (1), OP (2)))
2991 gcc_assert (GET_MODE (OP (2)) == QImode
);
2992 /* The MULU instruction does not support duplicate arguments
2993 but we know that if we copy OP (2) to X it will do so via
2994 A and thus OP (1) will already be loaded into A. */
2995 OP (2) = move_to_x (2, insn
);
2999 OP (1) = move_to_acc (1, insn
);
3003 /* If we omitted the move of OP1 into the accumulator (because
3004 it was already there from a previous insn), then force the
3005 generation of the move instruction now. We know that we
3006 are about to emit a move into HL (or DE) via AX, and hence
3007 our optimization to remove the load of OP1 is no longer valid. */
3008 if (tmp_id
== get_max_insn_count ())
3009 force_into_acc (saved_op1
, insn
);
3011 /* We have to copy op2 to X, but that involves the acc, which
3012 already has a live value. Emit it before those insns. */
3015 first
= next_nonnote_nondebug_insn (prev
);
3017 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3019 OP (2) = move_to_x (2, first
);
3025 rl78_alloc_address_registers_macax (rtx insn
)
3028 bool replace_in_op0
= false;
3029 bool replace_in_op1
= false;
3033 /* Two different MEMs are not allowed. */
3035 for (op
= 2; op
>= 0; op
--)
3037 if (MEM_P (OP (op
)))
3039 if (op
== 0 && replace_in_op0
)
3041 if (op
== 1 && replace_in_op1
)
3047 /* If we replace a MEM, make sure that we replace it for all
3048 occurrences of the same MEM in the insn. */
3049 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3050 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3052 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3055 && ((GET_CODE (XEXP (OP (op
), 0)) == REG
3056 && REGNO (XEXP (OP (op
), 0)) == SP_REG
)
3057 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3058 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3060 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3061 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3069 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3072 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3082 /* Scan all insns and devirtualize them. */
3084 rl78_alloc_physical_registers (void)
3086 /* During most of the compile, gcc is dealing with virtual
3087 registers. At this point, we need to assign physical registers
3088 to the vitual ones, and copy in/out as needed. */
3091 enum attr_valloc valloc_method
;
3093 for (insn
= get_insns (); insn
; insn
= curr
)
3097 curr
= next_nonnote_nondebug_insn (insn
);
3100 && (GET_CODE (PATTERN (insn
)) == SET
3101 || GET_CODE (PATTERN (insn
)) == CALL
)
3102 && INSN_CODE (insn
) == -1)
3104 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3106 i
= recog (PATTERN (insn
), insn
, 0);
3112 INSN_CODE (insn
) = i
;
3116 cfun
->machine
->virt_insns_ok
= 0;
3117 cfun
->machine
->real_insns_ok
= 1;
3119 clear_content_memory ();
3121 for (insn
= get_insns (); insn
; insn
= curr
)
3125 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3130 clear_content_memory ();
3136 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3138 pattern
= PATTERN (insn
);
3139 if (GET_CODE (pattern
) == PARALLEL
)
3140 pattern
= XVECEXP (pattern
, 0, 0);
3141 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3142 clear_content_memory ();
3143 if (GET_CODE (pattern
) != SET
3144 && GET_CODE (pattern
) != CALL
)
3146 if (GET_CODE (pattern
) == SET
3147 && GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3150 valloc_method
= get_attr_valloc (insn
);
3152 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3154 if (valloc_method
== VALLOC_MACAX
)
3156 record_content (AX
, NULL_RTX
);
3157 record_content (BC
, NULL_RTX
);
3158 record_content (DE
, NULL_RTX
);
3161 if (insn_ok_now (insn
))
3164 INSN_CODE (insn
) = -1;
3166 if (RTX_FRAME_RELATED_P (insn
))
3167 virt_insn_was_frame
= 1;
3169 virt_insn_was_frame
= 0;
3171 switch (valloc_method
)
3174 rl78_alloc_physical_registers_op1 (insn
);
3177 rl78_alloc_physical_registers_op2 (insn
);
3180 rl78_alloc_physical_registers_ro1 (insn
);
3183 rl78_alloc_physical_registers_cmp (insn
);
3186 rl78_alloc_physical_registers_umul (insn
);
3189 /* Macro that clobbers AX. */
3190 rl78_alloc_address_registers_macax (insn
);
3191 record_content (AX
, NULL_RTX
);
3192 record_content (BC
, NULL_RTX
);
3193 record_content (DE
, NULL_RTX
);
3197 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3198 clear_content_memory ();
3200 process_postponed_content_update ();
3204 fprintf (stderr
, "\033[0m");
3208 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3209 This function scans for uses of registers; the last use (i.e. first
3210 encounter when scanning backwards) triggers a REG_DEAD note if the
3211 reg was previously in DEAD[]. */
3213 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3222 code
= GET_CODE (s
);
3226 /* Compare registers by number. */
3231 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3232 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3233 print_rtl_single (dump_file
, s
);
3236 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3237 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3241 /* These codes have no constituent expressions
3252 /* These are kept unique for a given value. */
3259 fmt
= GET_RTX_FORMAT (code
);
3261 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3266 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3267 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3269 else if (fmt
[i
] == 'e')
3270 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3274 /* Like the previous function, but scan for SETs instead. */
3276 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3280 if (GET_CODE (d
) != REG
)
3285 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3287 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3288 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3292 /* This is a rather crude register death pass. Death status is reset
3293 at every jump or call insn. */
3295 rl78_calculate_death_notes (void)
3297 char dead
[FIRST_PSEUDO_REGISTER
];
3301 memset (dead
, 0, sizeof (dead
));
3303 for (insn
= get_last_insn ();
3305 insn
= prev_nonnote_nondebug_insn (insn
))
3309 fprintf (dump_file
, "\n--------------------------------------------------");
3310 fprintf (dump_file
, "\nDead:");
3311 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3313 fprintf (dump_file
, " %s", reg_names
[i
]);
3314 fprintf (dump_file
, "\n");
3315 print_rtl_single (dump_file
, insn
);
3318 switch (GET_CODE (insn
))
3322 switch (GET_CODE (p
))
3327 rl78_note_reg_set (dead
, d
, insn
);
3328 rl78_note_reg_uses (dead
, s
, insn
);
3332 rl78_note_reg_uses (dead
, p
, insn
);
3341 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3343 memset (dead
, 1, sizeof (dead
));
3344 /* We expect a USE just prior to this, which will mark
3345 the actual return registers. The USE will have a
3346 death note, but we aren't going to be modifying it
3351 memset (dead
, 0, sizeof (dead
));
3358 print_rtl_single (dump_file
, insn
);
3362 /* Helper function to reset the origins in RP and the age in AGE for
3365 reset_origins (int *rp
, int *age
)
3368 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3375 /* The idea behind this optimization is to look for cases where we
3376 move data from A to B to C, and instead move from A to B, and A to
3377 C. If B is a virtual register or memory, this is a big win on its
3378 own. If B turns out to be unneeded after this, it's a bigger win.
3379 For each register, we try to determine where it's value originally
3380 came from, if it's propogated purely through moves (and not
3381 computes). The ORIGINS[] array has the regno for the "origin" of
3382 the value in the [regno] it's indexed by. */
3384 rl78_propogate_register_origins (void)
3386 int origins
[FIRST_PSEUDO_REGISTER
];
3387 int age
[FIRST_PSEUDO_REGISTER
];
3389 rtx insn
, ninsn
= NULL_RTX
;
3392 reset_origins (origins
, age
);
3394 for (insn
= get_insns (); insn
; insn
= ninsn
)
3396 ninsn
= next_nonnote_nondebug_insn (insn
);
3400 fprintf (dump_file
, "\n");
3401 fprintf (dump_file
, "Origins:");
3402 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3403 if (origins
[i
] != i
)
3404 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
3405 fprintf (dump_file
, "\n");
3406 print_rtl_single (dump_file
, insn
);
3409 switch (GET_CODE (insn
))
3415 reset_origins (origins
, age
);
3422 pat
= PATTERN (insn
);
3424 if (GET_CODE (pat
) == PARALLEL
)
3426 rtx clobber
= XVECEXP (pat
, 0, 1);
3427 pat
= XVECEXP (pat
, 0, 0);
3428 if (GET_CODE (clobber
) == CLOBBER
3429 && GET_CODE (XEXP (clobber
, 0)) == REG
)
3431 int cr
= REGNO (XEXP (clobber
, 0));
3432 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
3434 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
3435 for (i
= 0; i
< mb
; i
++)
3437 origins
[cr
+ i
] = cr
+ i
;
3445 if (GET_CODE (pat
) == SET
)
3447 rtx src
= SET_SRC (pat
);
3448 rtx dest
= SET_DEST (pat
);
3449 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3451 if (GET_CODE (dest
) == REG
)
3453 int dr
= REGNO (dest
);
3455 if (GET_CODE (src
) == REG
)
3457 int sr
= REGNO (src
);
3459 int best_age
, best_reg
;
3461 /* See if the copy is not needed. */
3462 for (i
= 0; i
< mb
; i
++)
3463 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3468 fprintf (dump_file
, "deleting because dest already has correct value\n");
3473 if (dr
< 8 || sr
>= 8)
3479 /* See if the copy can be made from another
3480 bank 0 register instead, instead of the
3481 virtual src register. */
3482 for (ar
= 0; ar
< 8; ar
+= mb
)
3485 for (i
= 0; i
< mb
; i
++)
3486 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3489 /* The chip has some reg-reg move limitations. */
3490 if (mb
== 1 && dr
> 3)
3495 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3497 best_age
= age
[sr
+ i
];
3505 /* FIXME: copy debug info too. */
3506 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3511 for (i
= 0; i
< mb
; i
++)
3513 origins
[dr
+ i
] = origins
[sr
+ i
];
3514 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3519 /* The destination is computed, its origin is itself. */
3521 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3522 dr
, mb
, mb
== 1 ? "" : "s");
3523 for (i
= 0; i
< mb
; i
++)
3525 origins
[dr
+ i
] = dr
+ i
;
3530 /* Any registers marked with that reg as an origin are reset. */
3531 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3532 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3539 /* Special case - our ADDSI3 macro uses AX and sometimes BC. */
3540 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3543 fprintf (dump_file
, "Resetting origin of AX/BC for macro.\n");
3544 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3545 if (i
<= 3 || origins
[i
] <= 3)
3552 if (GET_CODE (src
) == ASHIFT
3553 || GET_CODE (src
) == ASHIFTRT
3554 || GET_CODE (src
) == LSHIFTRT
)
3556 rtx count
= XEXP (src
, 1);
3557 if (GET_CODE (count
) == REG
)
3559 /* Special case - our pattern clobbers the count register. */
3560 int r
= REGNO (count
);
3562 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
3563 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3564 if (i
== r
|| origins
[i
] == r
)
3572 else if (GET_CODE (pat
) == CLOBBER
3573 && GET_CODE (XEXP (pat
, 0)) == REG
)
3575 if (REG_P (XEXP (pat
, 0)))
3577 unsigned int reg
= REGNO (XEXP (pat
, 0));
3587 /* Remove any SETs where the destination is unneeded. */
3589 rl78_remove_unused_sets (void)
3591 rtx insn
, ninsn
= NULL_RTX
;
3594 for (insn
= get_insns (); insn
; insn
= ninsn
)
3596 ninsn
= next_nonnote_nondebug_insn (insn
);
3598 if ((insn
= single_set (insn
)) == NULL_RTX
)
3601 dest
= SET_DEST (insn
);
3603 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
3606 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
3611 /* This is the top of the devritualization pass. */
3615 /* split2 only happens when optimizing, but we need all movSIs to be
3620 rl78_alloc_physical_registers ();
3624 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
3625 print_rtl_with_bb (dump_file
, get_insns (), 0);
3628 rl78_propogate_register_origins ();
3629 rl78_calculate_death_notes ();
3633 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
3634 print_rtl_with_bb (dump_file
, get_insns (), 0);
3635 fprintf (dump_file
, "\n======================================================================\n");
3638 rl78_remove_unused_sets ();
3640 /* The code after devirtualizing has changed so much that at this point
3641 we might as well just rescan everything. Note that
3642 df_rescan_all_insns is not going to help here because it does not
3643 touch the artificial uses and defs. */
3644 df_finish_pass (true);
3646 df_live_add_problem ();
3647 df_scan_alloc (NULL
);
3654 #undef TARGET_RETURN_IN_MEMORY
3655 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
3658 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
3660 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
3661 return (size
== -1 || size
> 8);
3665 #undef TARGET_RTX_COSTS
3666 #define TARGET_RTX_COSTS rl78_rtx_costs
3668 static bool rl78_rtx_costs (rtx x
,
3670 int outer_code ATTRIBUTE_UNUSED
,
3671 int opno ATTRIBUTE_UNUSED
,
3673 bool speed ATTRIBUTE_UNUSED
)
3675 if (code
== IF_THEN_ELSE
)
3676 return COSTS_N_INSNS (10);
3677 if (GET_MODE (x
) == SImode
)
3683 *total
= COSTS_N_INSNS (14);
3684 else if (RL78_MUL_G13
)
3685 *total
= COSTS_N_INSNS (29);
3687 *total
= COSTS_N_INSNS (500);
3690 *total
= COSTS_N_INSNS (8);
3695 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3697 switch (INTVAL (XEXP (x
, 1)))
3699 case 0: *total
= COSTS_N_INSNS (0); break;
3700 case 1: *total
= COSTS_N_INSNS (6); break;
3701 case 2: case 3: case 4: case 5: case 6: case 7:
3702 *total
= COSTS_N_INSNS (10); break;
3703 case 8: *total
= COSTS_N_INSNS (6); break;
3704 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
3705 *total
= COSTS_N_INSNS (10); break;
3706 case 16: *total
= COSTS_N_INSNS (3); break;
3707 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
3708 *total
= COSTS_N_INSNS (4); break;
3709 case 24: *total
= COSTS_N_INSNS (4); break;
3710 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
3711 *total
= COSTS_N_INSNS (5); break;
3715 *total
= COSTS_N_INSNS (10+4*16);
3723 #undef TARGET_UNWIND_WORD_MODE
3724 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
3726 static enum machine_mode
3727 rl78_unwind_word_mode (void)
3733 struct gcc_target targetm
= TARGET_INITIALIZER
;
3735 #include "gt-rl78.h"