1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2017 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"
31 #include "stringpool.h"
36 #include "diagnostic-core.h"
38 #include "stor-layout.h"
41 #include "insn-attr.h"
46 #include "langhooks.h"
47 #include "tree-pass.h"
49 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
52 /* This file should be included last. */
53 #include "target-def.h"
55 static inline bool is_interrupt_func (const_tree decl
);
56 static inline bool is_brk_interrupt_func (const_tree decl
);
57 static void rl78_reorg (void);
58 static const char *rl78_strip_name_encoding (const char *);
59 static const char *rl78_strip_nonasm_name_encoding (const char *);
60 static section
* rl78_select_section (tree
, int, unsigned HOST_WIDE_INT
);
63 /* Debugging statements are tagged with DEBUG0 only so that they can
64 be easily enabled individually, by replacing the '0' with '1' as
69 /* REGISTER_NAMES has the names for individual 8-bit registers, but
70 these have the names we need to use when referring to 16-bit
72 static const char * const word_regnames
[] =
74 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
75 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
76 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
77 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
78 "sp", "ap", "psw", "es", "cs"
81 /* Structure for G13 MDUC registers. */
85 enum machine_mode mode
;
88 struct mduc_reg_type mduc_regs
[] =
98 struct GTY(()) machine_function
100 /* If set, the rest of the fields have been computed. */
102 /* Which register pairs need to be pushed in the prologue. */
103 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
105 /* These fields describe the frame layout... */
107 /* 4 bytes for saved PC */
110 int framesize_locals
;
111 int framesize_outgoing
;
115 /* If set, recog is allowed to match against the "real" patterns. */
117 /* If set, recog is allowed to match against the "virtual" patterns. */
119 /* Set if the current function needs to clean up any trampolines. */
120 int trampolines_used
;
121 /* True if the ES register is used and hence
122 needs to be saved inside interrupt handlers. */
126 /* This is our init_machine_status, as set in
127 rl78_option_override. */
128 static struct machine_function
*
129 rl78_init_machine_status (void)
131 struct machine_function
*m
;
133 m
= ggc_cleared_alloc
<machine_function
> ();
134 m
->virt_insns_ok
= 1;
139 /* This pass converts virtual instructions using virtual registers, to
140 real instructions using real registers. Rather than run it as
141 reorg, we reschedule it before vartrack to help with debugging. */
144 const pass_data pass_data_rl78_devirt
=
148 OPTGROUP_NONE
, /* optinfo_flags */
149 TV_MACH_DEP
, /* tv_id */
150 0, /* properties_required */
151 0, /* properties_provided */
152 0, /* properties_destroyed */
153 0, /* todo_flags_start */
154 0, /* todo_flags_finish */
157 class pass_rl78_devirt
: public rtl_opt_pass
160 pass_rl78_devirt (gcc::context
*ctxt
)
161 : rtl_opt_pass (pass_data_rl78_devirt
, ctxt
)
165 /* opt_pass methods: */
166 virtual unsigned int execute (function
*)
175 make_pass_rl78_devirt (gcc::context
*ctxt
)
177 return new pass_rl78_devirt (ctxt
);
180 /* Redundant move elimination pass. Must be run after the basic block
181 reordering pass for the best effect. */
184 move_elim_pass (void)
186 rtx_insn
*insn
, *ninsn
;
189 for (insn
= get_insns (); insn
; insn
= ninsn
)
193 ninsn
= next_nonnote_nondebug_insn (insn
);
195 if ((set
= single_set (insn
)) == NULL_RTX
)
201 /* If we have two SET insns in a row (without anything
202 between them) and the source of the second one is the
203 destination of the first one, and vice versa, then we
204 can eliminate the second SET. */
206 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
207 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
208 /* ... and none of the operands are volatile. */
209 && ! volatile_refs_p (SET_SRC (prev
))
210 && ! volatile_refs_p (SET_DEST (prev
))
211 && ! volatile_refs_p (SET_SRC (set
))
212 && ! volatile_refs_p (SET_DEST (set
)))
215 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
226 print_rtl_with_bb (dump_file
, get_insns (), 0);
233 const pass_data pass_data_rl78_move_elim
=
236 "move_elim", /* name */
237 OPTGROUP_NONE
, /* optinfo_flags */
238 TV_MACH_DEP
, /* tv_id */
239 0, /* properties_required */
240 0, /* properties_provided */
241 0, /* properties_destroyed */
242 0, /* todo_flags_start */
243 0, /* todo_flags_finish */
246 class pass_rl78_move_elim
: public rtl_opt_pass
249 pass_rl78_move_elim (gcc::context
*ctxt
)
250 : rtl_opt_pass (pass_data_rl78_move_elim
, ctxt
)
254 /* opt_pass methods: */
255 virtual unsigned int execute (function
*) { return move_elim_pass (); }
260 make_pass_rl78_move_elim (gcc::context
*ctxt
)
262 return new pass_rl78_move_elim (ctxt
);
265 #undef TARGET_ASM_FILE_START
266 #define TARGET_ASM_FILE_START rl78_asm_file_start
269 rl78_asm_file_start (void)
275 /* The memory used is 0xffec8 to 0xffedf; real registers are in
276 0xffee0 to 0xffee7. */
277 for (i
= 8; i
< 32; i
++)
278 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
282 for (i
= 0; i
< 8; i
++)
284 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
285 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
286 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
290 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
291 struct register_pass_info rl78_devirt_info
=
296 PASS_POS_INSERT_BEFORE
299 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
300 struct register_pass_info rl78_move_elim_info
=
305 PASS_POS_INSERT_AFTER
308 register_pass (& rl78_devirt_info
);
309 register_pass (& rl78_move_elim_info
);
313 rl78_output_symbol_ref (FILE * file
, rtx sym
)
315 tree type
= SYMBOL_REF_DECL (sym
);
316 const char *str
= XSTR (sym
, 0);
320 fputs (str
+ 1, file
);
324 str
= rl78_strip_nonasm_name_encoding (str
);
325 if (type
&& TREE_CODE (type
) == FUNCTION_DECL
)
327 fprintf (file
, "%%code(");
328 assemble_name (file
, str
);
332 assemble_name (file
, str
);
336 #undef TARGET_OPTION_OVERRIDE
337 #define TARGET_OPTION_OVERRIDE rl78_option_override
339 #define MUST_SAVE_MDUC_REGISTERS \
340 (TARGET_SAVE_MDUC_REGISTERS \
341 && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
344 rl78_option_override (void)
346 flag_omit_frame_pointer
= 1;
347 flag_no_function_cse
= 1;
348 flag_split_wide_types
= 0;
350 init_machine_status
= rl78_init_machine_status
;
356 for (i
= 24; i
< 32; i
++)
361 && strcmp (lang_hooks
.name
, "GNU C")
362 && strcmp (lang_hooks
.name
, "GNU C11")
363 && strcmp (lang_hooks
.name
, "GNU C17")
364 && strcmp (lang_hooks
.name
, "GNU C89")
365 && strcmp (lang_hooks
.name
, "GNU C99")
366 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
367 && strcmp (lang_hooks
.name
, "GNU GIMPLE"))
368 /* Address spaces are currently only supported by C. */
369 error ("-mes0 can only be used with C");
371 if (TARGET_SAVE_MDUC_REGISTERS
&& !(TARGET_G13
|| RL78_MUL_G13
))
372 warning (0, "mduc registers only saved for G13 target");
374 switch (rl78_cpu_type
)
377 rl78_cpu_type
= CPU_G14
;
378 if (rl78_mul_type
== MUL_UNINIT
)
379 rl78_mul_type
= MUL_NONE
;
383 switch (rl78_mul_type
)
385 case MUL_UNINIT
: rl78_mul_type
= MUL_NONE
; break;
386 case MUL_NONE
: break;
387 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
388 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
393 switch (rl78_mul_type
)
395 case MUL_UNINIT
: rl78_mul_type
= MUL_G13
; break;
396 case MUL_NONE
: break;
398 /* The S2 core does not have mul/div instructions. */
399 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
404 switch (rl78_mul_type
)
406 case MUL_UNINIT
: rl78_mul_type
= MUL_G14
; break;
407 case MUL_NONE
: break;
409 /* The G14 core does not have the hardware multiply peripheral used by the
410 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
411 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
417 /* Most registers are 8 bits. Some are 16 bits because, for example,
418 gcc doesn't like dealing with $FP as a register pair (the second
419 half of $fp is also 2 to keep reload happy wrt register pairs, but
420 no register class includes it). This table maps register numbers
422 static const int register_sizes
[] =
424 1, 1, 1, 1, 1, 1, 1, 1,
425 1, 1, 1, 1, 1, 1, 1, 1,
426 1, 1, 1, 1, 1, 1, 2, 2,
427 1, 1, 1, 1, 1, 1, 1, 1,
431 /* Predicates used in the MD patterns. This one is true when virtual
432 insns may be matched, which typically means before (or during) the
435 rl78_virt_insns_ok (void)
438 return cfun
->machine
->virt_insns_ok
;
442 /* Predicates used in the MD patterns. This one is true when real
443 insns may be matched, which typically means after (or during) the
446 rl78_real_insns_ok (void)
449 return cfun
->machine
->real_insns_ok
;
453 #undef TARGET_HARD_REGNO_NREGS
454 #define TARGET_HARD_REGNO_NREGS rl78_hard_regno_nregs
457 rl78_hard_regno_nregs (unsigned int regno
, machine_mode mode
)
459 int rs
= register_sizes
[regno
];
462 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
465 #undef TARGET_HARD_REGNO_MODE_OK
466 #define TARGET_HARD_REGNO_MODE_OK rl78_hard_regno_mode_ok
469 rl78_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
471 int s
= GET_MODE_SIZE (mode
);
475 /* These are not to be used by gcc. */
476 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
478 /* $fp can always be accessed as a 16-bit value. */
479 if (regno
== FP_REG
&& s
== 2)
483 /* Since a reg-reg move is really a reg-mem move, we must
484 enforce alignment. */
485 if (s
> 1 && (regno
% 2))
490 return (mode
== BImode
);
491 /* All other registers must be accessed in their natural sizes. */
492 if (s
== register_sizes
[regno
])
497 #undef TARGET_MODES_TIEABLE_P
498 #define TARGET_MODES_TIEABLE_P rl78_modes_tieable_p
501 rl78_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
503 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
504 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
505 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
506 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
509 /* Simplify_gen_subreg() doesn't handle memory references the way we
510 need it to below, so we use this function for when we must get a
511 valid subreg in a "natural" state. */
513 rl78_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
515 if (GET_CODE (r
) == MEM
)
516 return adjust_address (r
, mode
, byte
);
518 return simplify_gen_subreg (mode
, r
, omode
, byte
);
521 /* Used by movsi. Split SImode moves into two HImode moves, using
522 appropriate patterns for the upper and lower halves of symbols. */
524 rl78_expand_movsi (rtx
*operands
)
526 rtx op00
, op02
, op10
, op12
;
528 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
529 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
530 if (GET_CODE (operands
[1]) == CONST
531 || GET_CODE (operands
[1]) == SYMBOL_REF
)
533 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
534 op10
= gen_rtx_CONST (HImode
, op10
);
535 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
536 op12
= gen_rtx_CONST (HImode
, op12
);
540 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
541 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
544 if (rtx_equal_p (operands
[0], operands
[1]))
546 else if (rtx_equal_p (op00
, op12
))
548 emit_move_insn (op02
, op12
);
549 emit_move_insn (op00
, op10
);
553 emit_move_insn (op00
, op10
);
554 emit_move_insn (op02
, op12
);
558 /* Generate code to move an SImode value. */
560 rl78_split_movsi (rtx
*operands
, machine_mode omode
)
562 rtx op00
, op02
, op10
, op12
;
564 op00
= rl78_subreg (HImode
, operands
[0], omode
, 0);
565 op02
= rl78_subreg (HImode
, operands
[0], omode
, 2);
567 if (GET_CODE (operands
[1]) == CONST
568 || GET_CODE (operands
[1]) == SYMBOL_REF
)
570 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
571 op10
= gen_rtx_CONST (HImode
, op10
);
572 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
573 op12
= gen_rtx_CONST (HImode
, op12
);
577 op10
= rl78_subreg (HImode
, operands
[1], omode
, 0);
578 op12
= rl78_subreg (HImode
, operands
[1], omode
, 2);
581 if (rtx_equal_p (operands
[0], operands
[1]))
583 else if (rtx_equal_p (op00
, op12
))
599 /* Used by various two-operand expanders which cannot accept all
600 operands in the "far" namespace. Force some such operands into
601 registers so that each pattern has at most one far operand. */
603 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
608 /* FIXME: in the future, be smarter about only doing this if the
609 other operand is also far, assuming the devirtualizer can also
611 if (rl78_far_p (operands
[0]))
613 temp_reg
= operands
[0];
614 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
620 emit_insn (gen (operands
[0], operands
[1]));
622 emit_move_insn (temp_reg
, operands
[0]);
626 /* Likewise, but for three-operand expanders. */
628 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
633 /* FIXME: Likewise. */
634 if (rl78_far_p (operands
[1]))
636 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
637 emit_move_insn (temp_reg
, operands
[1]);
638 operands
[1] = temp_reg
;
641 if (rl78_far_p (operands
[0]))
643 temp_reg
= operands
[0];
644 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
650 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
652 emit_move_insn (temp_reg
, operands
[0]);
657 rl78_one_far_p (rtx
*operands
, int n
)
662 for (i
= 0; i
< n
; i
++)
663 if (rl78_far_p (operands
[i
]))
667 else if (rtx_equal_p (operands
[i
], which
))
674 #undef TARGET_CAN_ELIMINATE
675 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
678 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
683 /* Returns true if the given register needs to be saved by the
686 need_to_save (unsigned int regno
)
688 if (is_interrupt_func (cfun
->decl
))
690 /* We don't know what devirt will need */
694 /* We don't need to save registers that have
695 been reserved for interrupt handlers. */
699 /* If the handler is a non-leaf function then it may call
700 non-interrupt aware routines which will happily clobber
701 any call_used registers, so we have to preserve them.
702 We do not have to worry about the frame pointer register
703 though, as that is handled below. */
704 if (!crtl
->is_leaf
&& call_used_regs
[regno
] && regno
< 22)
707 /* Otherwise we only have to save a register, call_used
708 or not, if it is used by this handler. */
709 return df_regs_ever_live_p (regno
);
712 if (regno
== FRAME_POINTER_REGNUM
713 && (frame_pointer_needed
|| df_regs_ever_live_p (regno
)))
715 if (fixed_regs
[regno
])
717 if (crtl
->calls_eh_return
)
719 if (df_regs_ever_live_p (regno
)
720 && !call_used_regs
[regno
])
725 /* We use this to wrap all emitted insns in the prologue. */
729 RTX_FRAME_RELATED_P (x
) = 1;
733 /* Compute all the frame-related fields in our machine_function
736 rl78_compute_frame_info (void)
740 cfun
->machine
->computed
= 1;
741 cfun
->machine
->framesize_regs
= 0;
742 cfun
->machine
->framesize_locals
= get_frame_size ();
743 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
745 for (i
= 0; i
< 16; i
++)
746 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
748 cfun
->machine
->need_to_push
[i
] = 1;
749 cfun
->machine
->framesize_regs
+= 2;
752 cfun
->machine
->need_to_push
[i
] = 0;
754 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
755 cfun
->machine
->framesize_locals
++;
757 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
758 + cfun
->machine
->framesize_locals
759 + cfun
->machine
->framesize_outgoing
);
762 /* Returns true if the provided function has the specified attribute. */
764 has_func_attr (const_tree decl
, const char * func_attr
)
766 if (decl
== NULL_TREE
)
767 decl
= current_function_decl
;
769 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
772 /* Returns true if the provided function has the "interrupt" attribute. */
774 is_interrupt_func (const_tree decl
)
776 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
779 /* Returns true if the provided function has the "brk_interrupt" attribute. */
781 is_brk_interrupt_func (const_tree decl
)
783 return has_func_attr (decl
, "brk_interrupt");
786 /* Check "interrupt" attributes. */
788 rl78_handle_func_attribute (tree
* node
,
791 int flags ATTRIBUTE_UNUSED
,
794 gcc_assert (DECL_P (* node
));
795 gcc_assert (args
== NULL_TREE
);
797 if (TREE_CODE (* node
) != FUNCTION_DECL
)
799 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
801 * no_add_attrs
= true;
804 /* FIXME: We ought to check that the interrupt and exception
805 handler attributes have been applied to void functions. */
809 /* Check "naked" attributes. */
811 rl78_handle_naked_attribute (tree
* node
,
812 tree name ATTRIBUTE_UNUSED
,
814 int flags ATTRIBUTE_UNUSED
,
817 gcc_assert (DECL_P (* node
));
818 gcc_assert (args
== NULL_TREE
);
820 if (TREE_CODE (* node
) != FUNCTION_DECL
)
822 warning (OPT_Wattributes
, "naked attribute only applies to functions");
823 * no_add_attrs
= true;
826 /* Disable warnings about this function - eg reaching the end without
827 seeing a return statement - because the programmer is doing things
828 that gcc does not know about. */
829 TREE_NO_WARNING (* node
) = 1;
834 /* Check "saddr" attributes. */
836 rl78_handle_saddr_attribute (tree
* node
,
838 tree args ATTRIBUTE_UNUSED
,
839 int flags ATTRIBUTE_UNUSED
,
842 gcc_assert (DECL_P (* node
));
844 if (TREE_CODE (* node
) == FUNCTION_DECL
)
846 warning (OPT_Wattributes
, "%qE attribute doesn't apply to functions",
848 * no_add_attrs
= true;
854 #undef TARGET_ATTRIBUTE_TABLE
855 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
857 /* Table of RL78-specific attributes. */
858 const struct attribute_spec rl78_attribute_table
[] =
860 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
861 affects_type_identity. */
862 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
864 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
866 { "naked", 0, 0, true, false, false, rl78_handle_naked_attribute
,
868 { "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute
,
870 { NULL
, 0, 0, false, false, false, NULL
, false, NULL
}
875 /* Break down an address RTX into its component base/index/addend
876 portions and return TRUE if the address is of a valid form, else
879 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
885 if (GET_CODE (x
) == UNSPEC
886 && XINT (x
, 1) == UNS_ES_ADDR
)
887 x
= XVECEXP (x
, 0, 1);
889 if (GET_CODE (x
) == REG
)
895 /* We sometimes get these without the CONST wrapper */
896 if (GET_CODE (x
) == PLUS
897 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
898 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
904 if (GET_CODE (x
) == PLUS
)
909 if (GET_CODE (*base
) == SUBREG
)
911 if (GET_MODE (*base
) == HImode
912 && GET_MODE (XEXP (*base
, 0)) == SImode
913 && GET_CODE (XEXP (*base
, 0)) == REG
)
915 /* This is a throw-away rtx just to tell everyone
916 else what effective register we're using. */
917 *base
= gen_rtx_REG (HImode
, REGNO (XEXP (*base
, 0)));
921 if (GET_CODE (*base
) != REG
922 && GET_CODE (x
) == REG
)
929 if (GET_CODE (*base
) != REG
)
932 if (GET_CODE (x
) == ZERO_EXTEND
933 && GET_CODE (XEXP (x
, 0)) == REG
)
935 *index
= XEXP (x
, 0);
940 switch (GET_CODE (x
))
943 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
944 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
955 switch (GET_CODE (XEXP (x
, 0)))
979 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
982 rl78_hl_b_c_addr_p (rtx op
)
986 if (GET_CODE (op
) != PLUS
)
990 if (GET_CODE (hl
) == ZERO_EXTEND
)
996 if (GET_CODE (hl
) != REG
)
998 if (GET_CODE (bc
) != ZERO_EXTEND
)
1001 if (GET_CODE (bc
) != REG
)
1003 if (REGNO (hl
) != HL_REG
)
1005 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
1011 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
1013 /* Return the appropriate mode for a named address address. */
1015 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1016 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
1018 static scalar_int_mode
1019 rl78_addr_space_address_mode (addr_space_t addrspace
)
1023 case ADDR_SPACE_GENERIC
:
1025 case ADDR_SPACE_NEAR
:
1027 case ADDR_SPACE_FAR
:
1034 /* Used in various constraints and predicates to match operands in the
1035 "far" address space. */
1042 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx (x
);
1043 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
1046 /* Not all far addresses are legitimate, because the devirtualizer
1047 can't handle them. */
1048 if (! rl78_as_legitimate_address (GET_MODE (x
), XEXP (x
, 0), false, ADDR_SPACE_FAR
))
1051 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x
))) == 32;
1054 /* Return the appropriate mode for a named address pointer. */
1055 #undef TARGET_ADDR_SPACE_POINTER_MODE
1056 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1058 static scalar_int_mode
1059 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
1063 case ADDR_SPACE_GENERIC
:
1065 case ADDR_SPACE_NEAR
:
1067 case ADDR_SPACE_FAR
:
1074 /* Returns TRUE for valid addresses. */
1075 #undef TARGET_VALID_POINTER_MODE
1076 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1079 rl78_valid_pointer_mode (scalar_int_mode m
)
1081 return (m
== HImode
|| m
== SImode
);
1084 #undef TARGET_LEGITIMATE_CONSTANT_P
1085 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1088 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
1094 #define TARGET_LRA_P hook_bool_void_false
1096 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1097 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1100 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
1101 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
1103 rtx base
, index
, addend
;
1104 bool is_far_addr
= false;
1107 as_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (as
));
1109 if (GET_CODE (x
) == UNSPEC
1110 && XINT (x
, 1) == UNS_ES_ADDR
)
1112 x
= XVECEXP (x
, 0, 1);
1116 if (as_bits
== 16 && is_far_addr
)
1119 if (! characterize_address (x
, &base
, &index
, &addend
))
1122 /* We can't extract the high/low portions of a PLUS address
1123 involving a register during devirtualization, so make sure all
1124 such __far addresses do not have addends. This forces GCC to do
1125 the sum separately. */
1126 if (addend
&& base
&& as_bits
== 32 && GET_MODE (base
) == SImode
)
1131 int ir
= REGNO (index
);
1132 int br
= REGNO (base
);
1134 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1135 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
1136 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
1140 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
1143 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
1144 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
1150 /* Determine if one named address space is a subset of another. */
1151 #undef TARGET_ADDR_SPACE_SUBSET_P
1152 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1155 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1160 subset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset
));
1161 superset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset
));
1163 return (subset_bits
<= superset_bits
);
1166 #undef TARGET_ADDR_SPACE_CONVERT
1167 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1169 /* Convert from one address space to another. */
1171 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1173 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1174 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1179 to_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as
));
1180 from_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as
));
1182 if (to_bits
< from_bits
)
1185 /* This is unpredictable, as we're truncating off usable address
1188 warning (OPT_Waddress
, "converting far pointer to near pointer");
1189 result
= gen_reg_rtx (HImode
);
1190 if (GET_CODE (op
) == SYMBOL_REF
1191 || (GET_CODE (op
) == REG
&& REGNO (op
) >= FIRST_PSEUDO_REGISTER
))
1192 tmp
= gen_rtx_raw_SUBREG (HImode
, op
, 0);
1194 tmp
= simplify_subreg (HImode
, op
, SImode
, 0);
1195 gcc_assert (tmp
!= NULL_RTX
);
1196 emit_move_insn (result
, tmp
);
1199 else if (to_bits
> from_bits
)
1201 /* This always works. */
1202 result
= gen_reg_rtx (SImode
);
1203 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
1204 if (TREE_CODE (from_type
) == POINTER_TYPE
1205 && TREE_CODE (TREE_TYPE (from_type
)) == FUNCTION_TYPE
)
1206 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
1208 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), GEN_INT (0x0f));
1216 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1218 rl78_regno_mode_code_ok_for_base_p (int regno
, machine_mode mode ATTRIBUTE_UNUSED
,
1219 addr_space_t address_space ATTRIBUTE_UNUSED
,
1220 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
1222 if (regno
<= SP_REG
&& regno
>= 16)
1224 if (index_code
== REG
)
1225 return (regno
== HL_REG
);
1226 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
1231 /* Implements MODE_CODE_BASE_REG_CLASS. */
1233 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED
,
1234 addr_space_t address_space ATTRIBUTE_UNUSED
,
1235 int outer_code ATTRIBUTE_UNUSED
,
1236 int index_code ATTRIBUTE_UNUSED
)
1241 /* Typical stack layout should looks like this after the function's prologue:
1246 | | arguments saved | Increasing
1247 | | on the stack | addresses
1248 PARENT arg pointer -> | | /
1249 -------------------------- ---- -------------------
1250 CHILD |ret | return address
1255 frame pointer -> | | /
1263 | | outgoing | Decreasing
1264 | | arguments | addresses
1265 current stack pointer -> | | / |
1266 -------------------------- ---- ------------------ V
1269 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1270 described in the machine_Function struct definition, above. */
1272 rl78_initial_elimination_offset (int from
, int to
)
1274 int rv
= 0; /* as if arg to arg */
1276 rl78_compute_frame_info ();
1280 case STACK_POINTER_REGNUM
:
1281 rv
+= cfun
->machine
->framesize_outgoing
;
1282 rv
+= cfun
->machine
->framesize_locals
;
1284 case FRAME_POINTER_REGNUM
:
1285 rv
+= cfun
->machine
->framesize_regs
;
1294 case FRAME_POINTER_REGNUM
:
1296 rv
-= cfun
->machine
->framesize_regs
;
1297 case ARG_POINTER_REGNUM
:
1307 rl78_is_naked_func (void)
1309 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1312 /* Check if the block uses mul/div insns for G13 target. */
1315 check_mduc_usage (void)
1320 FOR_EACH_BB_FN (bb
, cfun
)
1322 FOR_BB_INSNS (bb
, insn
)
1325 && (get_attr_is_g13_muldiv_insn (insn
) == IS_G13_MULDIV_INSN_YES
))
1332 /* Expand the function prologue (from the prologue pattern). */
1335 rl78_expand_prologue (void)
1338 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1339 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1342 if (rl78_is_naked_func ())
1345 /* Always re-compute the frame info - the register usage may have changed. */
1346 rl78_compute_frame_info ();
1348 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1349 cfun
->machine
->framesize
+= ARRAY_SIZE (mduc_regs
) * 2;
1351 if (flag_stack_usage_info
)
1352 current_function_static_stack_size
= cfun
->machine
->framesize
;
1354 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1355 for (i
= 0; i
< 4; i
++)
1356 if (cfun
->machine
->need_to_push
[i
])
1358 /* Select Bank 0 if we are using any registers from Bank 0. */
1359 emit_insn (gen_sel_rb (GEN_INT (0)));
1363 for (i
= 0; i
< 16; i
++)
1364 if (cfun
->machine
->need_to_push
[i
])
1372 emit_move_insn (ax
, gen_rtx_REG (HImode
, reg
));
1378 int need_bank
= i
/4;
1380 if (need_bank
!= rb
)
1382 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1387 F (emit_insn (gen_push (gen_rtx_REG (HImode
, reg
))));
1391 emit_insn (gen_sel_rb (GEN_INT (0)));
1393 /* Save ES register inside interrupt functions if it is used. */
1394 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1396 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode
, A_REG
)));
1397 F (emit_insn (gen_push (ax
)));
1400 /* Save MDUC registers inside interrupt routine. */
1401 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1403 for (unsigned i
= 0; i
< ARRAY_SIZE (mduc_regs
); i
++)
1405 mduc_reg_type
*reg
= mduc_regs
+ i
;
1406 rtx mem_mduc
= gen_rtx_MEM (reg
->mode
, GEN_INT (reg
->address
));
1408 MEM_VOLATILE_P (mem_mduc
) = 1;
1409 if (reg
->mode
== QImode
)
1410 emit_insn (gen_movqi (gen_rtx_REG (QImode
, A_REG
), mem_mduc
));
1412 emit_insn (gen_movhi (gen_rtx_REG (HImode
, AX_REG
), mem_mduc
));
1414 emit_insn (gen_push (gen_rtx_REG (HImode
, AX_REG
)));
1418 if (frame_pointer_needed
)
1420 F (emit_move_insn (ax
, sp
));
1421 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
), ax
));
1424 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1427 /* If we need to subtract more than 254*3 then it is faster and
1428 smaller to move SP into AX and perform the subtraction there. */
1433 emit_move_insn (ax
, sp
);
1434 emit_insn (gen_subhi3 (ax
, ax
, GEN_INT (fs
)));
1435 insn
= F (emit_move_insn (sp
, ax
));
1436 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
1437 gen_rtx_SET (sp
, gen_rtx_PLUS (HImode
, sp
,
1444 int fs_byte
= (fs
> 254) ? 254 : fs
;
1446 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1453 /* Expand the function epilogue (from the epilogue pattern). */
1455 rl78_expand_epilogue (void)
1458 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1459 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1462 if (rl78_is_naked_func ())
1465 if (frame_pointer_needed
)
1467 emit_move_insn (ax
, gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1468 emit_move_insn (sp
, ax
);
1472 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1475 emit_move_insn (ax
, sp
);
1476 emit_insn (gen_addhi3 (ax
, ax
, GEN_INT (fs
)));
1477 emit_move_insn (sp
, ax
);
1483 int fs_byte
= (fs
> 254) ? 254 : fs
;
1485 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1491 /* Restore MDUC registers from interrupt routine. */
1492 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1494 for (int i
= ARRAY_SIZE (mduc_regs
) - 1; i
>= 0; i
--)
1496 mduc_reg_type
*reg
= mduc_regs
+ i
;
1497 rtx mem_mduc
= gen_rtx_MEM (reg
->mode
, GEN_INT (reg
->address
));
1499 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1500 MEM_VOLATILE_P (mem_mduc
) = 1;
1501 if (reg
->mode
== QImode
)
1502 emit_insn (gen_movqi (mem_mduc
, gen_rtx_REG (QImode
, A_REG
)));
1504 emit_insn (gen_movhi (mem_mduc
, gen_rtx_REG (HImode
, AX_REG
)));
1508 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1510 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1511 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode
, A_REG
)));
1514 for (i
= 15; i
>= 0; i
--)
1515 if (cfun
->machine
->need_to_push
[i
])
1517 rtx dest
= gen_rtx_REG (HImode
, i
* 2);
1522 emit_insn (gen_pop (dest
));
1525 emit_insn (gen_pop (ax
));
1526 emit_move_insn (dest
, ax
);
1527 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1528 emit_insn (gen_use (dest
));
1533 int need_bank
= i
/ 4;
1535 if (need_bank
!= rb
)
1537 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1540 emit_insn (gen_pop (dest
));
1545 emit_insn (gen_sel_rb (GEN_INT (0)));
1547 if (cfun
->machine
->trampolines_used
)
1548 emit_insn (gen_trampoline_uninit ());
1550 if (is_brk_interrupt_func (cfun
->decl
))
1551 emit_jump_insn (gen_brk_interrupt_return ());
1552 else if (is_interrupt_func (cfun
->decl
))
1553 emit_jump_insn (gen_interrupt_return ());
1555 emit_jump_insn (gen_rl78_return ());
1558 /* Likewise, for exception handlers. */
1560 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1562 /* FIXME - replace this with an indirect jump with stack adjust. */
1563 emit_jump_insn (gen_rl78_return ());
1566 #undef TARGET_ASM_FUNCTION_PROLOGUE
1567 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1569 /* We don't use this to actually emit the function prologue. We use
1570 this to insert a comment in the asm file describing the
1573 rl78_start_function (FILE *file
)
1577 if (cfun
->machine
->framesize
== 0)
1579 fprintf (file
, "\t; start of function\n");
1581 if (cfun
->machine
->framesize_regs
)
1583 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1584 for (i
= 0; i
< 16; i
++)
1585 if (cfun
->machine
->need_to_push
[i
])
1586 fprintf (file
, " %s", word_regnames
[i
*2]);
1587 fprintf (file
, "\n");
1590 if (frame_pointer_needed
)
1591 fprintf (file
, "\t; $fp points here (r22)\n");
1593 if (cfun
->machine
->framesize_locals
)
1594 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1595 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1597 if (cfun
->machine
->framesize_outgoing
)
1598 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1599 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1601 if (cfun
->machine
->uses_es
)
1602 fprintf (file
, "\t; uses ES register\n");
1604 if (MUST_SAVE_MDUC_REGISTERS
)
1605 fprintf (file
, "\t; preserves MDUC registers\n");
1608 /* Return an RTL describing where a function return value of type RET_TYPE
1611 #undef TARGET_FUNCTION_VALUE
1612 #define TARGET_FUNCTION_VALUE rl78_function_value
1615 rl78_function_value (const_tree ret_type
,
1616 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1617 bool outgoing ATTRIBUTE_UNUSED
)
1619 machine_mode mode
= TYPE_MODE (ret_type
);
1621 return gen_rtx_REG (mode
, 8);
1624 #undef TARGET_PROMOTE_FUNCTION_MODE
1625 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1628 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1630 int *punsignedp ATTRIBUTE_UNUSED
,
1631 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1636 /* Return an RTL expression describing the register holding a function
1637 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1638 be passed on the stack. CUM describes the previous parameters to the
1639 function and NAMED is false if the parameter is part of a variable
1640 parameter list, or the last named parameter before the start of a
1641 variable parameter list. */
1643 #undef TARGET_FUNCTION_ARG
1644 #define TARGET_FUNCTION_ARG rl78_function_arg
1647 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1648 machine_mode mode ATTRIBUTE_UNUSED
,
1649 const_tree type ATTRIBUTE_UNUSED
,
1650 bool named ATTRIBUTE_UNUSED
)
1655 #undef TARGET_FUNCTION_ARG_ADVANCE
1656 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1659 rl78_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
, const_tree type
,
1660 bool named ATTRIBUTE_UNUSED
)
1663 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1665 rounded_size
= ((mode
== BLKmode
)
1666 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1667 if (rounded_size
& 1)
1669 (*cum
) += rounded_size
;
1672 #undef TARGET_FUNCTION_ARG_BOUNDARY
1673 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1676 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED
,
1677 const_tree type ATTRIBUTE_UNUSED
)
1682 /* Supported modifier letters:
1684 A - address of a MEM
1685 S - SADDR form of a real register
1686 v - real register corresponding to a virtual register
1687 m - minus - negative of CONST_INT value.
1688 C - inverse of a conditional (NE vs EQ for example)
1689 C - complement of an integer
1690 z - collapsed conditional
1691 s - shift count mod 8
1692 S - shift count mod 16
1693 r - reverse shift count (8-(count mod 8))
1696 h - bottom HI of an SI
1698 q - bottom QI of an HI
1700 e - third QI of an SI (i.e. where the ES register gets values from)
1701 E - fourth QI of an SI (i.e. MSB)
1703 p - Add +0 to a zero-indexed HL based address.
1706 /* Implements the bulk of rl78_print_operand, below. We do it this
1707 way because we need to test for a constant at the top level and
1708 insert the '#', but not test for it anywhere else as we recurse
1709 down into the operand. */
1711 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1715 switch (GET_CODE (op
))
1719 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1722 if (rl78_far_p (op
))
1724 fprintf (file
, "es:");
1725 if (GET_CODE (XEXP (op
, 0)) == UNSPEC
)
1726 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1730 op
= adjust_address (op
, HImode
, 2);
1735 op
= adjust_address (op
, HImode
, 0);
1740 op
= adjust_address (op
, QImode
, 1);
1745 op
= adjust_address (op
, QImode
, 0);
1750 op
= adjust_address (op
, QImode
, 2);
1755 op
= adjust_address (op
, QImode
, 3);
1758 if (CONSTANT_P (XEXP (op
, 0)))
1760 if (!rl78_saddr_p (op
))
1761 fprintf (file
, "!");
1762 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1764 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1765 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1767 if (!rl78_saddr_p (op
))
1768 fprintf (file
, "!");
1769 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1771 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1772 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1773 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1775 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1776 fprintf (file
, "[");
1777 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1778 if (letter
== 'p' && GET_CODE (XEXP (op
, 0)) == REG
)
1779 fprintf (file
, "+0");
1780 fprintf (file
, "]");
1785 fprintf (file
, "[");
1786 rl78_print_operand_1 (file
, op
, letter
);
1787 if (letter
== 'p' && REG_P (op
) && REGNO (op
) == 6)
1788 fprintf (file
, "+0");
1789 fprintf (file
, "]");
1796 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1797 else if (letter
== 'H')
1798 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1799 else if (letter
== 'q')
1800 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1801 else if (letter
== 'e')
1802 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1803 else if (letter
== 'E')
1804 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1805 else if (letter
== 'S')
1806 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1807 else if (GET_MODE (op
) == HImode
1808 && ! (REGNO (op
) & ~0xfe))
1811 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1813 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1816 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1821 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1822 else if (letter
== 'H')
1823 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1824 else if (letter
== 'q')
1825 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1826 else if (letter
== 'h')
1827 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1828 else if (letter
== 'e')
1829 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1830 else if (letter
== 'B')
1832 int ival
= INTVAL (op
);
1835 if (exact_log2 (ival
) >= 0)
1836 fprintf (file
, "%d", exact_log2 (ival
));
1838 fprintf (file
, "%d", exact_log2 (~ival
& 0xff));
1840 else if (letter
== 'E')
1841 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1842 else if (letter
== 'm')
1843 fprintf (file
, "%ld", - INTVAL (op
));
1844 else if (letter
== 's')
1845 fprintf (file
, "%ld", INTVAL (op
) % 8);
1846 else if (letter
== 'S')
1847 fprintf (file
, "%ld", INTVAL (op
) % 16);
1848 else if (letter
== 'r')
1849 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1850 else if (letter
== 'C')
1851 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1853 fprintf (file
, "%ld", INTVAL (op
));
1857 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1862 int bits
= INTVAL (XEXP (op
, 1));
1863 int ofs
= INTVAL (XEXP (op
, 2));
1864 if (bits
== 16 && ofs
== 0)
1865 fprintf (file
, "%%lo16(");
1866 else if (bits
== 16 && ofs
== 16)
1867 fprintf (file
, "%%hi16(");
1868 else if (bits
== 8 && ofs
== 16)
1869 fprintf (file
, "%%hi8(");
1872 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1873 fprintf (file
, ")");
1878 if (GET_CODE (XEXP (op
, 0)) == REG
)
1879 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1881 print_rtl (file
, op
);
1888 fprintf (file
, "%%hi16(");
1894 fprintf (file
, "%%lo16(");
1900 fprintf (file
, "%%hi8(");
1904 if (letter
== 'q' || letter
== 'Q')
1905 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1907 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1909 if (GET_CODE (XEXP (op
, 1)) == SYMBOL_REF
1910 && SYMBOL_REF_DECL (XEXP (op
, 1))
1911 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 1))) == FUNCTION_DECL
)
1913 fprintf (file
, "%%code(");
1914 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 1), 0)));
1915 fprintf (file
, "+");
1916 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1917 fprintf (file
, ")");
1921 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1922 fprintf (file
, "+");
1923 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1928 if (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1929 && SYMBOL_REF_DECL (XEXP (op
, 0))
1930 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 0))) == FUNCTION_DECL
)
1932 fprintf (file
, "%%code(");
1933 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 0), 0)));
1934 fprintf (file
, "+");
1935 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1936 fprintf (file
, ")");
1940 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1941 fprintf (file
, "+");
1942 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1946 fprintf (file
, ")");
1950 if (GET_MODE (op
) == HImode
1951 && SUBREG_BYTE (op
) == 0)
1953 fprintf (file
, "%%lo16(");
1954 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1955 fprintf (file
, ")");
1957 else if (GET_MODE (op
) == HImode
1958 && SUBREG_BYTE (op
) == 2)
1960 fprintf (file
, "%%hi16(");
1961 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1962 fprintf (file
, ")");
1966 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1974 fprintf (file
, "%%hi16(");
1980 fprintf (file
, "%%lo16(");
1986 fprintf (file
, "%%hi8(");
1990 if (letter
== 'q' || letter
== 'Q')
1991 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1993 if (SYMBOL_REF_DECL (op
) && TREE_CODE (SYMBOL_REF_DECL (op
)) == FUNCTION_DECL
)
1995 fprintf (file
, "%%code(");
1996 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
1997 fprintf (file
, ")");
2000 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
2002 fprintf (file
, ")");
2007 output_asm_label (op
);
2012 fprintf (file
, "#comparison eliminated");
2014 fprintf (file
, letter
== 'C' ? "nc" : "c");
2018 fprintf (file
, "br");
2020 fprintf (file
, letter
== 'C' ? "h" : "nh");
2024 fprintf (file
, "br");
2026 fprintf (file
, letter
== 'C' ? "c" : "nc");
2030 fprintf (file
, "#comparison eliminated");
2032 fprintf (file
, letter
== 'C' ? "nh" : "h");
2036 fprintf (file
, "br");
2038 fprintf (file
, letter
== 'C' ? "nz" : "z");
2042 fprintf (file
, "#comparison eliminated");
2044 fprintf (file
, letter
== 'C' ? "z" : "nz");
2047 /* Note: these assume appropriate adjustments were made so that
2048 unsigned comparisons, which is all this chip has, will
2052 fprintf (file
, "#comparison eliminated");
2054 fprintf (file
, letter
== 'C' ? "nc" : "c");
2058 fprintf (file
, "br");
2060 fprintf (file
, letter
== 'C' ? "h" : "nh");
2064 fprintf (file
, "br");
2066 fprintf (file
, letter
== 'C' ? "c" : "nc");
2070 fprintf (file
, "#comparison eliminated");
2072 fprintf (file
, letter
== 'C' ? "nh" : "h");
2076 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
2081 #undef TARGET_PRINT_OPERAND
2082 #define TARGET_PRINT_OPERAND rl78_print_operand
2085 rl78_print_operand (FILE * file
, rtx op
, int letter
)
2087 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
2088 fprintf (file
, "#");
2089 rl78_print_operand_1 (file
, op
, letter
);
2092 #undef TARGET_TRAMPOLINE_INIT
2093 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
2095 /* Note that the RL78's addressing makes it very difficult to do
2096 trampolines on the stack. So, libgcc has a small pool of
2097 trampolines from which one is allocated to this task. */
2099 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2101 rtx mov_addr
, thunk_addr
;
2102 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
2104 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
2105 thunk_addr
= gen_reg_rtx (HImode
);
2107 function
= force_reg (HImode
, function
);
2108 static_chain
= force_reg (HImode
, static_chain
);
2110 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
2111 emit_move_insn (mov_addr
, thunk_addr
);
2113 cfun
->machine
->trampolines_used
= 1;
2116 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2117 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2120 rl78_trampoline_adjust_address (rtx m_tramp
)
2122 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
2126 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2127 the "normal" compares, specifically, it only has unsigned compares,
2128 so we must synthesize the missing ones. */
2130 rl78_expand_compare (rtx
*operands
)
2132 if (GET_CODE (operands
[2]) == MEM
)
2133 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
2138 /* Define this to 1 if you are debugging the peephole optimizers. */
2139 #define DEBUG_PEEP 0
2141 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2142 The default "word" size is a byte so we can effectively use all the
2143 registers, but we want to do 16-bit moves whenever possible. This
2144 function determines when such a move is an option. */
2146 rl78_peep_movhi_p (rtx
*operands
)
2151 /* (set (op0) (op1))
2152 (set (op2) (op3)) */
2154 if (! rl78_virt_insns_ok ())
2158 fprintf (stderr
, "\033[33m");
2159 debug_rtx (operands
[0]);
2160 debug_rtx (operands
[1]);
2161 debug_rtx (operands
[2]);
2162 debug_rtx (operands
[3]);
2163 fprintf (stderr
, "\033[0m");
2166 /* You can move a constant to memory as QImode, but not HImode. */
2167 if (GET_CODE (operands
[0]) == MEM
2168 && GET_CODE (operands
[1]) != REG
)
2171 fprintf (stderr
, "no peep: move constant to memory\n");
2176 if (rtx_equal_p (operands
[0], operands
[3]))
2179 fprintf (stderr
, "no peep: overlapping\n");
2184 for (i
= 0; i
< 2; i
++)
2186 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
2189 fprintf (stderr
, "no peep: different codes\n");
2193 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
2196 fprintf (stderr
, "no peep: different modes\n");
2201 switch (GET_CODE (operands
[i
]))
2205 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
2206 || GET_MODE (operands
[i
]) != QImode
)
2209 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
2210 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
2215 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
2218 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
2228 if (GET_MODE (operands
[i
]) != QImode
)
2230 if (MEM_ALIGN (operands
[i
]) < 16)
2232 a
= XEXP (operands
[i
], 0);
2233 if (GET_CODE (a
) == CONST
)
2235 if (GET_CODE (a
) == PLUS
)
2237 if (GET_CODE (a
) == CONST_INT
2241 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
2242 debug_rtx (operands
[i
]);
2246 m
= adjust_address (operands
[i
], QImode
, 1);
2247 if (! rtx_equal_p (m
, operands
[i
+2]))
2250 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
2252 debug_rtx (operands
[i
+2]);
2260 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
2266 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
2271 /* Likewise, when a peephole is activated, this function helps compute
2272 the new operands. */
2274 rl78_setup_peep_movhi (rtx
*operands
)
2278 for (i
= 0; i
< 2; i
++)
2280 switch (GET_CODE (operands
[i
]))
2283 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
2287 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char) INTVAL (operands
[i
+2])) * 256);
2291 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
2301 How Devirtualization works in the RL78 GCC port
2305 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2306 bytes of register space, in four banks, memory-mapped. One bank is
2307 the "selected" bank and holds the registers used for primary
2308 operations. Since the registers are memory mapped, often you can
2309 still refer to the unselected banks via memory accesses.
2313 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2314 and refers to the other banks via their memory addresses, although
2315 they're treated as regular registers internally. These "virtual"
2316 registers are R8 through R23 (bank3 is reserved for asm-based
2317 interrupt handlers).
2319 There are four machine description files:
2321 rl78.md - common register-independent patterns and definitions
2322 rl78-expand.md - expanders
2323 rl78-virt.md - patterns that match BEFORE devirtualization
2324 rl78-real.md - patterns that match AFTER devirtualization
2326 At least through register allocation and reload, gcc is told that it
2327 can do pretty much anything - but may only use the virtual registers.
2328 GCC cannot properly create the varying addressing modes that the RL78
2329 supports in an efficient way.
2331 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2332 uses the "valloc" attribute in rl78-virt.md for determining the rules
2333 by which it will replace virtual registers with real registers (or
2334 not) and how to make up addressing modes. For example, insns tagged
2335 with "ro1" have a single read-only parameter, which may need to be
2336 moved from memory/constant/vreg to a suitable real register. As part
2337 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2338 patterns and enabling the rl78-real.md patterns. The new patterns'
2339 constraints are used to determine the real registers used. NOTE:
2340 patterns in rl78-virt.md essentially ignore the constrains and rely on
2341 predicates, where the rl78-real.md ones essentially ignore the
2342 predicates and rely on the constraints.
2344 The devirtualization pass is scheduled via the pass manager (despite
2345 being called "rl78_reorg") so it can be scheduled prior to var-track
2346 (the idea is to let gdb know about the new registers). Ideally, it
2347 would be scheduled right after pro/epilogue generation, so the
2348 post-reload optimizers could operate on the real registers, but when I
2349 tried that there were some issues building the target libraries.
2351 During devirtualization, a simple register move optimizer is run. It
2352 would be better to run a full CSE/propogation pass on it though, but
2353 that has not yet been attempted.
2356 #define DEBUG_ALLOC 0
2358 #define OP(x) (*recog_data.operand_loc[x])
2360 /* This array is used to hold knowledge about the contents of the
2361 real registers (A ... H), the memory-based registers (r8 ... r31)
2362 and the first NUM_STACK_LOCS words on the stack. We use this to
2363 avoid generating redundant move instructions.
2365 A value in the range 0 .. 31 indicates register A .. r31.
2366 A value in the range 32 .. 63 indicates stack slot (value - 32).
2367 A value of NOT_KNOWN indicates that the contents of that location
2370 #define NUM_STACK_LOCS 32
2371 #define NOT_KNOWN 127
2373 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
2375 static unsigned char saved_update_index
= NOT_KNOWN
;
2376 static unsigned char saved_update_value
;
2377 static machine_mode saved_update_mode
;
2381 clear_content_memory (void)
2383 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
2385 fprintf (dump_file
, " clear content memory\n");
2386 saved_update_index
= NOT_KNOWN
;
2389 /* Convert LOC into an index into the content_memory array.
2390 If LOC cannot be converted, return NOT_KNOWN. */
2392 static unsigned char
2393 get_content_index (rtx loc
)
2397 if (loc
== NULL_RTX
)
2402 if (REGNO (loc
) < 32)
2407 mode
= GET_MODE (loc
);
2409 if (! rl78_stack_based_mem (loc
, mode
))
2412 loc
= XEXP (loc
, 0);
2415 /* loc = MEM (SP) */
2418 /* loc = MEM (PLUS (SP, INT)). */
2419 loc
= XEXP (loc
, 1);
2421 if (INTVAL (loc
) < NUM_STACK_LOCS
)
2422 return 32 + INTVAL (loc
);
2427 /* Return a string describing content INDEX in mode MODE.
2428 WARNING: Can return a pointer to a static buffer. */
2430 get_content_name (unsigned char index
, machine_mode mode
)
2432 static char buffer
[128];
2434 if (index
== NOT_KNOWN
)
2438 sprintf (buffer
, "stack slot %d", index
- 32);
2439 else if (mode
== HImode
)
2440 sprintf (buffer
, "%s%s",
2441 reg_names
[index
+ 1], reg_names
[index
]);
2443 return reg_names
[index
];
2451 display_content_memory (FILE * file
)
2455 fprintf (file
, " Known memory contents:\n");
2457 for (i
= 0; i
< sizeof content_memory
; i
++)
2458 if (content_memory
[i
] != NOT_KNOWN
)
2460 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
2461 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2467 update_content (unsigned char index
, unsigned char val
, machine_mode mode
)
2471 gcc_assert (index
< sizeof content_memory
);
2473 content_memory
[index
] = val
;
2474 if (val
!= NOT_KNOWN
)
2475 content_memory
[val
] = index
;
2477 /* Make the entry in dump_file *before* VAL is increased below. */
2480 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2481 if (val
== NOT_KNOWN
)
2482 fprintf (dump_file
, "Unknown\n");
2484 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2489 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2491 content_memory
[index
+ 1] = val
;
2492 if (val
!= NOT_KNOWN
)
2494 content_memory
[val
] = index
+ 1;
2499 /* Any other places that had INDEX recorded as their contents are now invalid. */
2500 for (i
= 0; i
< sizeof content_memory
; i
++)
2503 || (val
!= NOT_KNOWN
&& i
== val
))
2510 if (content_memory
[i
] == index
2511 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2513 content_memory
[i
] = NOT_KNOWN
;
2516 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2519 content_memory
[++ i
] = NOT_KNOWN
;
2524 /* Record that LOC contains VALUE.
2525 For HImode locations record that LOC+1 contains VALUE+1.
2526 If LOC is not a register or stack slot, do nothing.
2527 If VALUE is not a register or stack slot, clear the recorded content. */
2530 record_content (rtx loc
, rtx value
)
2533 unsigned char index
;
2536 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2539 val
= get_content_index (value
);
2541 mode
= GET_MODE (loc
);
2548 /* This should not happen when optimizing. */
2550 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2551 get_content_name (val
, mode
));
2558 update_content (index
, val
, mode
);
2561 /* Returns TRUE if LOC already contains a copy of VALUE. */
2564 already_contains (rtx loc
, rtx value
)
2566 unsigned char index
;
2569 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2572 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2575 if (content_memory
[index
] != val
)
2578 if (GET_MODE (loc
) == HImode
)
2579 return content_memory
[index
+ 1] == val
+ 1;
2585 rl78_es_addr (rtx addr
)
2587 if (GET_CODE (addr
) == MEM
)
2588 addr
= XEXP (addr
, 0);
2589 if (GET_CODE (addr
) != UNSPEC
)
2591 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2597 rl78_es_base (rtx addr
)
2599 if (GET_CODE (addr
) == MEM
)
2600 addr
= XEXP (addr
, 0);
2601 addr
= XVECEXP (addr
, 0, 1);
2602 if (GET_CODE (addr
) == CONST
2603 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2604 addr
= XEXP (XEXP (addr
, 0), 0);
2605 /* Mode doesn't matter here. */
2606 return gen_rtx_MEM (HImode
, addr
);
2609 /* Rescans an insn to see if it's recognized again. This is done
2610 carefully to ensure that all the constraint information is accurate
2611 for the newly matched insn. */
2613 insn_ok_now (rtx_insn
* insn
)
2615 rtx pattern
= PATTERN (insn
);
2618 INSN_CODE (insn
) = -1;
2620 if (recog (pattern
, insn
, 0) > -1)
2622 extract_insn (insn
);
2623 if (constrain_operands (1, get_preferred_alternatives (insn
)))
2626 fprintf (stderr
, "\033[32m");
2628 fprintf (stderr
, "\033[0m");
2630 if (SET_P (pattern
))
2631 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2633 /* We need to detect far addresses that haven't been
2634 converted to es/lo16 format. */
2635 for (i
=0; i
<recog_data
.n_operands
; i
++)
2636 if (GET_CODE (OP (i
)) == MEM
2637 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2638 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2646 /* We need to re-recog the insn with virtual registers to get
2648 cfun
->machine
->virt_insns_ok
= 1;
2649 if (recog (pattern
, insn
, 0) > -1)
2651 extract_insn (insn
);
2652 if (constrain_operands (0, get_preferred_alternatives (insn
)))
2654 cfun
->machine
->virt_insns_ok
= 0;
2660 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2667 fprintf (stderr
, "\033[31m");
2669 fprintf (stderr
, "\033[0m");
2675 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2676 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2677 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2678 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2679 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2681 #define FAILED gcc_unreachable ()
2682 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2683 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2686 /* Registers into which we move the contents of virtual registers. */
2687 #define X gen_rtx_REG (QImode, X_REG)
2688 #define A gen_rtx_REG (QImode, A_REG)
2689 #define C gen_rtx_REG (QImode, C_REG)
2690 #define B gen_rtx_REG (QImode, B_REG)
2691 #define E gen_rtx_REG (QImode, E_REG)
2692 #define D gen_rtx_REG (QImode, D_REG)
2693 #define L gen_rtx_REG (QImode, L_REG)
2694 #define H gen_rtx_REG (QImode, H_REG)
2696 #define AX gen_rtx_REG (HImode, AX_REG)
2697 #define BC gen_rtx_REG (HImode, BC_REG)
2698 #define DE gen_rtx_REG (HImode, DE_REG)
2699 #define HL gen_rtx_REG (HImode, HL_REG)
2701 /* Returns TRUE if R is a virtual register. */
2703 is_virtual_register (rtx r
)
2705 return (GET_CODE (r
) == REG
2710 /* In all these alloc routines, we expect the following: the insn
2711 pattern is unshared, the insn was previously recognized and failed
2712 due to predicates or constraints, and the operand data is in
2715 static int virt_insn_was_frame
;
2717 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2720 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2723 fprintf (stderr
, "\033[36m%d: ", line
);
2725 fprintf (stderr
, "\033[0m");
2727 /*SCHED_GROUP_P (r) = 1;*/
2728 if (virt_insn_was_frame
)
2729 RTX_FRAME_RELATED_P (r
) = 1;
2733 #define EM(x) EM2 (__LINE__, x)
2735 /* Return a suitable RTX for the low half of a __far address. */
2737 rl78_lo16 (rtx addr
)
2741 if (GET_CODE (addr
) == SYMBOL_REF
2742 || GET_CODE (addr
) == CONST
)
2744 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2745 r
= gen_rtx_CONST (HImode
, r
);
2748 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2750 r
= gen_es_addr (r
);
2751 cfun
->machine
->uses_es
= true;
2756 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2760 if (GET_CODE (addr
) == SYMBOL_REF
2761 || GET_CODE (addr
) == CONST
)
2763 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2764 r
= gen_rtx_CONST (QImode
, r
);
2767 return rl78_subreg (QImode
, addr
, SImode
, 2);
2771 add_postponed_content_update (rtx to
, rtx value
)
2773 unsigned char index
;
2775 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2778 gcc_assert (saved_update_index
== NOT_KNOWN
);
2779 saved_update_index
= index
;
2780 saved_update_value
= get_content_index (value
);
2781 saved_update_mode
= GET_MODE (to
);
2785 process_postponed_content_update (void)
2787 if (saved_update_index
!= NOT_KNOWN
)
2789 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2790 saved_update_index
= NOT_KNOWN
;
2794 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2795 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2796 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2797 BEFORE is true, FROM otherwise. */
2799 gen_and_emit_move (rtx to
, rtx from
, rtx_insn
*where
, bool before
)
2801 machine_mode mode
= GET_MODE (to
);
2803 if (optimize
&& before
&& already_contains (to
, from
))
2806 display_content_memory (stderr
);
2810 fprintf (dump_file
, " Omit move of %s into ",
2811 get_content_name (get_content_index (from
), mode
));
2812 fprintf (dump_file
, "%s as it already contains this value\n",
2813 get_content_name (get_content_index (to
), mode
));
2818 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2822 if (where
== NULL_RTX
)
2825 emit_insn_before (move
, where
);
2828 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2830 /* If necessary move REG_EH_REGION notes forward.
2831 cf. compiling gcc.dg/pr44545.c. */
2832 if (note
!= NULL_RTX
)
2834 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2835 remove_note (where
, note
);
2838 emit_insn_after (move
, where
);
2842 record_content (to
, from
);
2844 add_postponed_content_update (to
, from
);
2847 return before
? to
: from
;
2850 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2851 copy it into NEWBASE and return the updated MEM. Otherwise just
2852 return M. Any needed insns are emitted before BEFORE. */
2854 transcode_memory_rtx (rtx m
, rtx newbase
, rtx_insn
*before
)
2856 rtx base
, index
, addendr
;
2863 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2866 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2870 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2871 emit_insn_before (EM (gen_movqi_to_es (A
)), before
);
2874 record_content (A
, NULL_RTX
);
2876 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2877 MEM_COPY_ATTRIBUTES (new_m
, m
);
2882 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2883 gcc_assert (index
== NULL_RTX
);
2885 if (base
== NULL_RTX
)
2888 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2889 addend
= INTVAL (addendr
);
2891 gcc_assert (REG_P (base
));
2892 gcc_assert (REG_P (newbase
));
2894 int limit
= 256 - GET_MODE_SIZE (GET_MODE (m
));
2896 if (REGNO (base
) == SP_REG
)
2898 if (addend
>= 0 && addend
<= limit
)
2902 /* BASE should be a virtual register. We copy it to NEWBASE. If
2903 the addend is out of range for DE/HL, we use AX to compute the full
2907 || (addend
> limit
&& REGNO (newbase
) != BC_REG
)
2909 && (GET_CODE (addendr
) != CONST_INT
)
2910 && ((REGNO (newbase
) != BC_REG
))
2916 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2917 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2918 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2919 record_content (AX
, NULL_RTX
);
2920 record_content (newbase
, NULL_RTX
);
2928 base
= gen_and_emit_move (newbase
, base
, before
, true);
2933 record_content (base
, NULL_RTX
);
2934 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2938 record_content (base
, NULL_RTX
);
2939 base
= gen_rtx_PLUS (HImode
, base
, addendr
);
2944 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2945 cfun
->machine
->uses_es
= true;
2948 m
= change_address (m
, GET_MODE (m
), base
);
2952 /* Copy SRC to accumulator (A or AX), placing any generated insns
2953 before BEFORE. Returns accumulator RTX. */
2955 move_to_acc (int opno
, rtx_insn
*before
)
2957 rtx src
= OP (opno
);
2958 machine_mode mode
= GET_MODE (src
);
2960 if (REG_P (src
) && REGNO (src
) < 2)
2963 if (mode
== VOIDmode
)
2964 mode
= recog_data
.operand_mode
[opno
];
2966 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2970 force_into_acc (rtx src
, rtx_insn
*before
)
2972 machine_mode mode
= GET_MODE (src
);
2975 if (REG_P (src
) && REGNO (src
) < 2)
2978 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2982 emit_insn_before (move
, before
);
2983 record_content (AX
, NULL_RTX
);
2986 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2987 after AFTER. Returns accumulator RTX. */
2989 move_from_acc (unsigned int opno
, rtx_insn
*after
)
2991 rtx dest
= OP (opno
);
2992 machine_mode mode
= GET_MODE (dest
);
2994 if (REG_P (dest
) && REGNO (dest
) < 2)
2997 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
3000 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
3001 before BEFORE. Returns reg RTX. */
3003 move_acc_to_reg (rtx acc
, int regno
, rtx_insn
*before
)
3005 machine_mode mode
= GET_MODE (acc
);
3008 reg
= gen_rtx_REG (mode
, regno
);
3010 return gen_and_emit_move (reg
, acc
, before
, true);
3013 /* Copy SRC to X, placing any generated insns before BEFORE.
3016 move_to_x (int opno
, rtx_insn
*before
)
3018 rtx src
= OP (opno
);
3019 machine_mode mode
= GET_MODE (src
);
3022 if (mode
== VOIDmode
)
3023 mode
= recog_data
.operand_mode
[opno
];
3024 reg
= (mode
== QImode
) ? X
: AX
;
3026 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3028 OP (opno
) = move_to_acc (opno
, before
);
3029 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
3033 return gen_and_emit_move (reg
, src
, before
, true);
3036 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
3037 Returns H/HL RTX. */
3039 move_to_hl (int opno
, rtx_insn
*before
)
3041 rtx src
= OP (opno
);
3042 machine_mode mode
= GET_MODE (src
);
3045 if (mode
== VOIDmode
)
3046 mode
= recog_data
.operand_mode
[opno
];
3047 reg
= (mode
== QImode
) ? L
: HL
;
3049 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3051 OP (opno
) = move_to_acc (opno
, before
);
3052 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
3056 return gen_and_emit_move (reg
, src
, before
, true);
3059 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
3060 Returns E/DE RTX. */
3062 move_to_de (int opno
, rtx_insn
*before
)
3064 rtx src
= OP (opno
);
3065 machine_mode mode
= GET_MODE (src
);
3068 if (mode
== VOIDmode
)
3069 mode
= recog_data
.operand_mode
[opno
];
3071 reg
= (mode
== QImode
) ? E
: DE
;
3073 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3075 OP (opno
) = move_to_acc (opno
, before
);
3076 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
3080 gen_and_emit_move (reg
, src
, before
, true);
3086 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
3088 rl78_alloc_physical_registers_op1 (rtx_insn
* insn
)
3090 /* op[0] = func op[1] */
3092 /* We first try using A as the destination, then copying it
3094 if (rtx_equal_p (OP (0), OP (1)))
3097 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3101 /* If necessary, load the operands into BC and HL.
3102 Check to see if we already have OP (0) in HL
3103 and if so, swap the order.
3105 It is tempting to perform this optimization when OP(0) does
3106 not hold a MEM, but this leads to bigger code in general.
3107 The problem is that if OP(1) holds a MEM then swapping it
3108 into BC means a BC-relative load is used and these are 3
3109 bytes long vs 1 byte for an HL load. */
3111 && already_contains (HL
, XEXP (OP (0), 0)))
3113 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
3114 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
3118 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3119 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3125 OP (0) = move_from_acc (0, insn
);
3129 /* Try copying the src to acc first, then. This is for, for
3130 example, ZERO_EXTEND or NOT. */
3131 OP (1) = move_to_acc (1, insn
);
3136 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3137 Assumes that the current insn has already been recognised and hence the
3138 constraint data has been filled in. */
3140 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
3142 const char * p
= recog_data
.constraints
[opnum
];
3144 /* No constraints means anything is accepted. */
3145 if (p
== NULL
|| *p
== 0 || *p
== ',')
3154 len
= CONSTRAINT_LEN (c
, p
);
3155 gcc_assert (len
> 0);
3163 if (lookup_constraint (p
) == constraint
)
3171 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3173 rl78_alloc_physical_registers_op2 (rtx_insn
* insn
)
3181 if (rtx_equal_p (OP (0), OP (1)))
3186 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3187 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3192 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3193 OP (2) = transcode_memory_rtx (OP (2), DE
, insn
);
3196 else if (rtx_equal_p (OP (0), OP (2)))
3198 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3200 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3204 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3205 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3206 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3211 prev
= prev_nonnote_nondebug_insn (insn
);
3212 if (recog_data
.constraints
[1][0] == '%'
3213 && is_virtual_register (OP (1))
3214 && ! is_virtual_register (OP (2))
3215 && ! CONSTANT_P (OP (2)))
3222 /* Make a note of whether (H)L is being used. It matters
3223 because if OP (2) also needs reloading, then we must take
3224 care not to corrupt HL. */
3225 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
3227 /* If HL is not currently being used and dest == op1 then there are
3228 some possible optimizations available by reloading one of the
3229 operands into HL, before trying to use the accumulator. */
3232 && rtx_equal_p (OP (0), OP (1)))
3234 /* If op0 is a Ws1 type memory address then switching the base
3235 address register to HL might allow us to perform an in-memory
3236 operation. (eg for the INCW instruction).
3238 FIXME: Adding the move into HL is costly if this optimization is not
3239 going to work, so for now, make sure that we know that the new insn will
3240 match the requirements of the addhi3_real pattern. Really we ought to
3241 generate a candidate sequence, test that, and then install it if the
3242 results are good. */
3243 if (satisfies_constraint_Ws1 (OP (0))
3244 && has_constraint (0, CONSTRAINT_Wh1
)
3245 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3247 rtx base
, index
, addend
, newbase
;
3249 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
3250 gcc_assert (index
== NULL_RTX
);
3251 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3253 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3254 if (addend
!= NULL_RTX
)
3256 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
3257 record_content (newbase
, NULL_RTX
);
3258 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
3260 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
3262 /* We do not want to fail here as this means that
3263 we have inserted useless insns into the stream. */
3267 else if (REG_P (OP (0))
3268 && satisfies_constraint_Ws1 (OP (2))
3269 && has_constraint (2, CONSTRAINT_Wh1
))
3271 rtx base
, index
, addend
, newbase
;
3273 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
3274 gcc_assert (index
== NULL_RTX
);
3275 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3277 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3278 if (addend
!= NULL_RTX
)
3280 gen_and_emit_move (HL
, base
, insn
, true);
3282 if (REGNO (OP (0)) != X_REG
)
3284 OP (1) = move_to_acc (1, insn
);
3285 OP (0) = move_from_acc (0, insn
);
3288 record_content (HL
, NULL_RTX
);
3289 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
3291 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
3293 /* We do not want to fail here as this means that
3294 we have inserted useless insns into the stream. */
3300 OP (0) = move_from_acc (0, insn
);
3302 tmp_id
= get_max_insn_count ();
3305 if (rtx_equal_p (OP (1), OP (2)))
3306 OP (2) = OP (1) = move_to_acc (1, insn
);
3308 OP (1) = move_to_acc (1, insn
);
3312 /* If we omitted the move of OP1 into the accumulator (because
3313 it was already there from a previous insn), then force the
3314 generation of the move instruction now. We know that we
3315 are about to emit a move into HL (or DE) via AX, and hence
3316 our optimization to remove the load of OP1 is no longer valid. */
3317 if (tmp_id
== get_max_insn_count ())
3318 force_into_acc (saved_op1
, insn
);
3320 /* We have to copy op2 to HL (or DE), but that involves AX, which
3321 already has a live value. Emit it before those insns. */
3324 first
= next_nonnote_nondebug_insn (prev
);
3326 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3329 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
3334 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3336 rl78_alloc_physical_registers_ro1 (rtx_insn
* insn
)
3338 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3342 OP (0) = move_to_acc (0, insn
);
3347 /* Devirtualize a compare insn. */
3349 rl78_alloc_physical_registers_cmp (rtx_insn
* insn
)
3353 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3356 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3357 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3359 /* HI compares have to have OP (1) in AX, but QI
3360 compares do not, so it is worth checking here. */
3363 /* For an HImode compare, OP (1) must always be in AX.
3364 But if OP (1) is a REG (and not AX), then we can avoid
3365 a reload of OP (1) if we reload OP (2) into AX and invert
3368 && REGNO (OP (1)) != AX_REG
3369 && GET_MODE (OP (1)) == HImode
3372 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
3374 OP (2) = move_to_acc (2, insn
);
3376 switch (GET_CODE (cmp
))
3381 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
3382 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
3383 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
3384 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
3397 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
3398 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
3400 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
3405 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3406 should be handled by the second alternative of the cbranchhi_real pattern. */
3407 if (rtx_equal_p (OP (1), OP (2)))
3409 OP (1) = OP (2) = BC
;
3413 tmp_id
= get_max_insn_count ();
3416 OP (1) = move_to_acc (1, insn
);
3420 /* If we omitted the move of OP1 into the accumulator (because
3421 it was already there from a previous insn), then force the
3422 generation of the move instruction now. We know that we
3423 are about to emit a move into HL via AX, and hence our
3424 optimization to remove the load of OP1 is no longer valid. */
3425 if (tmp_id
== get_max_insn_count ())
3426 force_into_acc (saved_op1
, insn
);
3428 /* We have to copy op2 to HL, but that involves the acc, which
3429 already has a live value. Emit it before those insns. */
3431 first
= next_nonnote_nondebug_insn (prev
);
3433 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3435 OP (2) = move_to_hl (2, first
);
3440 /* Like op2, but AX = A * X. */
3442 rl78_alloc_physical_registers_umul (rtx_insn
* insn
)
3444 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3449 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3450 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3451 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3455 if (recog_data
.constraints
[1][0] == '%'
3456 && is_virtual_register (OP (1))
3457 && !is_virtual_register (OP (2))
3458 && !CONSTANT_P (OP (2)))
3465 OP (0) = move_from_acc (0, insn
);
3467 tmp_id
= get_max_insn_count ();
3470 if (rtx_equal_p (OP (1), OP (2)))
3472 gcc_assert (GET_MODE (OP (2)) == QImode
);
3473 /* The MULU instruction does not support duplicate arguments
3474 but we know that if we copy OP (2) to X it will do so via
3475 A and thus OP (1) will already be loaded into A. */
3476 OP (2) = move_to_x (2, insn
);
3480 OP (1) = move_to_acc (1, insn
);
3484 /* If we omitted the move of OP1 into the accumulator (because
3485 it was already there from a previous insn), then force the
3486 generation of the move instruction now. We know that we
3487 are about to emit a move into HL (or DE) via AX, and hence
3488 our optimization to remove the load of OP1 is no longer valid. */
3489 if (tmp_id
== get_max_insn_count ())
3490 force_into_acc (saved_op1
, insn
);
3492 /* We have to copy op2 to X, but that involves the acc, which
3493 already has a live value. Emit it before those insns. */
3496 first
= next_nonnote_nondebug_insn (prev
);
3498 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3500 OP (2) = move_to_x (2, first
);
3506 rl78_alloc_address_registers_macax (rtx_insn
* insn
)
3509 bool replace_in_op0
= false;
3510 bool replace_in_op1
= false;
3514 /* Two different MEMs are not allowed. */
3516 for (op
= 2; op
>= 0; op
--)
3518 if (MEM_P (OP (op
)))
3520 if (op
== 0 && replace_in_op0
)
3522 if (op
== 1 && replace_in_op1
)
3528 /* If we replace a MEM, make sure that we replace it for all
3529 occurrences of the same MEM in the insn. */
3530 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3531 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3533 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3536 && ((GET_CODE (XEXP (OP (op
), 0)) == REG
3537 && REGNO (XEXP (OP (op
), 0)) == SP_REG
)
3538 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3539 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3541 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3542 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3550 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3553 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3564 rl78_alloc_address_registers_div (rtx_insn
* insn
)
3569 /* Scan all insns and devirtualize them. */
3571 rl78_alloc_physical_registers (void)
3573 /* During most of the compile, gcc is dealing with virtual
3574 registers. At this point, we need to assign physical registers
3575 to the vitual ones, and copy in/out as needed. */
3577 rtx_insn
*insn
, *curr
;
3578 enum attr_valloc valloc_method
;
3580 for (insn
= get_insns (); insn
; insn
= curr
)
3584 curr
= next_nonnote_nondebug_insn (insn
);
3587 && (GET_CODE (PATTERN (insn
)) == SET
3588 || GET_CODE (PATTERN (insn
)) == CALL
)
3589 && INSN_CODE (insn
) == -1)
3591 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3593 i
= recog (PATTERN (insn
), insn
, 0);
3599 INSN_CODE (insn
) = i
;
3603 cfun
->machine
->virt_insns_ok
= 0;
3604 cfun
->machine
->real_insns_ok
= 1;
3606 clear_content_memory ();
3608 for (insn
= get_insns (); insn
; insn
= curr
)
3612 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3617 clear_content_memory ();
3623 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3625 pattern
= PATTERN (insn
);
3626 if (GET_CODE (pattern
) == PARALLEL
)
3627 pattern
= XVECEXP (pattern
, 0, 0);
3628 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3629 clear_content_memory ();
3630 if (GET_CODE (pattern
) != SET
3631 && GET_CODE (pattern
) != CALL
)
3633 if (GET_CODE (pattern
) == SET
3634 && GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3637 valloc_method
= get_attr_valloc (insn
);
3639 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3641 if (valloc_method
== VALLOC_MACAX
)
3643 record_content (AX
, NULL_RTX
);
3644 record_content (BC
, NULL_RTX
);
3645 record_content (DE
, NULL_RTX
);
3647 else if (valloc_method
== VALLOC_DIVHI
)
3649 record_content (AX
, NULL_RTX
);
3650 record_content (BC
, NULL_RTX
);
3652 else if (valloc_method
== VALLOC_DIVSI
)
3654 record_content (AX
, NULL_RTX
);
3655 record_content (BC
, NULL_RTX
);
3656 record_content (DE
, NULL_RTX
);
3657 record_content (HL
, NULL_RTX
);
3660 if (insn_ok_now (insn
))
3663 INSN_CODE (insn
) = -1;
3665 if (RTX_FRAME_RELATED_P (insn
))
3666 virt_insn_was_frame
= 1;
3668 virt_insn_was_frame
= 0;
3670 switch (valloc_method
)
3673 rl78_alloc_physical_registers_op1 (insn
);
3676 rl78_alloc_physical_registers_op2 (insn
);
3679 rl78_alloc_physical_registers_ro1 (insn
);
3682 rl78_alloc_physical_registers_cmp (insn
);
3685 rl78_alloc_physical_registers_umul (insn
);
3686 record_content (AX
, NULL_RTX
);
3689 /* Macro that clobbers AX. */
3690 rl78_alloc_address_registers_macax (insn
);
3691 record_content (AX
, NULL_RTX
);
3692 record_content (BC
, NULL_RTX
);
3693 record_content (DE
, NULL_RTX
);
3696 rl78_alloc_address_registers_div (insn
);
3697 record_content (AX
, NULL_RTX
);
3698 record_content (BC
, NULL_RTX
);
3699 record_content (DE
, NULL_RTX
);
3700 record_content (HL
, NULL_RTX
);
3703 rl78_alloc_address_registers_div (insn
);
3704 record_content (AX
, NULL_RTX
);
3705 record_content (BC
, NULL_RTX
);
3711 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3712 clear_content_memory ();
3714 process_postponed_content_update ();
3718 fprintf (stderr
, "\033[0m");
3722 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3723 This function scans for uses of registers; the last use (i.e. first
3724 encounter when scanning backwards) triggers a REG_DEAD note if the
3725 reg was previously in DEAD[]. */
3727 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3736 code
= GET_CODE (s
);
3740 /* Compare registers by number. */
3745 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3746 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3747 print_rtl_single (dump_file
, s
);
3750 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3751 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3755 /* These codes have no constituent expressions
3766 /* These are kept unique for a given value. */
3773 fmt
= GET_RTX_FORMAT (code
);
3775 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3780 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3781 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3783 else if (fmt
[i
] == 'e')
3784 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3788 /* Like the previous function, but scan for SETs instead. */
3790 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3794 if (GET_CODE (d
) == MEM
)
3795 rl78_note_reg_uses (dead
, XEXP (d
, 0), insn
);
3797 if (GET_CODE (d
) != REG
)
3802 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3804 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3805 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3809 /* This is a rather crude register death pass. Death status is reset
3810 at every jump or call insn. */
3812 rl78_calculate_death_notes (void)
3814 char dead
[FIRST_PSEUDO_REGISTER
];
3819 memset (dead
, 0, sizeof (dead
));
3821 for (insn
= get_last_insn ();
3823 insn
= prev_nonnote_nondebug_insn (insn
))
3827 fprintf (dump_file
, "\n--------------------------------------------------");
3828 fprintf (dump_file
, "\nDead:");
3829 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3831 fprintf (dump_file
, " %s", reg_names
[i
]);
3832 fprintf (dump_file
, "\n");
3833 print_rtl_single (dump_file
, insn
);
3836 switch (GET_CODE (insn
))
3840 if (GET_CODE (p
) == PARALLEL
)
3842 rtx q
= XVECEXP (p
, 0 ,1);
3844 /* This happens with the DIV patterns. */
3845 if (GET_CODE (q
) == SET
)
3849 rl78_note_reg_set (dead
, d
, insn
);
3850 rl78_note_reg_uses (dead
, s
, insn
);
3853 p
= XVECEXP (p
, 0, 0);
3856 switch (GET_CODE (p
))
3861 rl78_note_reg_set (dead
, d
, insn
);
3862 rl78_note_reg_uses (dead
, s
, insn
);
3866 rl78_note_reg_uses (dead
, p
, insn
);
3875 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3877 memset (dead
, 1, sizeof (dead
));
3878 /* We expect a USE just prior to this, which will mark
3879 the actual return registers. The USE will have a
3880 death note, but we aren't going to be modifying it
3886 memset (dead
, 0, sizeof (dead
));
3893 print_rtl_single (dump_file
, insn
);
3897 /* Helper function to reset the origins in RP and the age in AGE for
3900 reset_origins (int *rp
, int *age
)
3903 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3911 set_origin (rtx pat
, rtx_insn
* insn
, int * origins
, int * age
)
3913 rtx src
= SET_SRC (pat
);
3914 rtx dest
= SET_DEST (pat
);
3915 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3918 if (GET_CODE (dest
) == REG
)
3920 int dr
= REGNO (dest
);
3922 if (GET_CODE (src
) == REG
)
3924 int sr
= REGNO (src
);
3926 int best_age
, best_reg
;
3928 /* See if the copy is not needed. */
3929 for (i
= 0; i
< mb
; i
++)
3930 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3936 fprintf (dump_file
, "deleting because dest already has correct value\n");
3941 if (dr
< 8 || sr
>= 8)
3948 /* See if the copy can be made from another
3949 bank 0 register instead, instead of the
3950 virtual src register. */
3951 for (ar
= 0; ar
< 8; ar
+= mb
)
3955 for (i
= 0; i
< mb
; i
++)
3956 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3959 /* The chip has some reg-reg move limitations. */
3960 if (mb
== 1 && dr
> 3)
3965 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3967 best_age
= age
[sr
+ i
];
3975 /* FIXME: copy debug info too. */
3976 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3981 for (i
= 0; i
< mb
; i
++)
3983 origins
[dr
+ i
] = origins
[sr
+ i
];
3984 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3989 /* The destination is computed, its origin is itself. */
3991 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3992 dr
, mb
, mb
== 1 ? "" : "s");
3994 for (i
= 0; i
< mb
; i
++)
3996 origins
[dr
+ i
] = dr
+ i
;
4001 /* Any registers marked with that reg as an origin are reset. */
4002 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4003 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
4010 /* Special case - our MUL patterns uses AX and sometimes BC. */
4011 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
4014 fprintf (dump_file
, "Resetting origin of AX/BC for MUL pattern.\n");
4016 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4017 if (i
<= 3 || origins
[i
] <= 3)
4023 else if (get_attr_valloc (insn
) == VALLOC_DIVHI
)
4026 fprintf (dump_file
, "Resetting origin of AX/DE for DIVHI pattern.\n");
4028 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4033 || origins
[i
] == A_REG
4034 || origins
[i
] == X_REG
4035 || origins
[i
] == D_REG
4036 || origins
[i
] == E_REG
)
4042 else if (get_attr_valloc (insn
) == VALLOC_DIVSI
)
4045 fprintf (dump_file
, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
4047 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4048 if (i
<= 7 || origins
[i
] <= 7)
4055 if (GET_CODE (src
) == ASHIFT
4056 || GET_CODE (src
) == ASHIFTRT
4057 || GET_CODE (src
) == LSHIFTRT
)
4059 rtx count
= XEXP (src
, 1);
4061 if (GET_CODE (count
) == REG
)
4063 /* Special case - our pattern clobbers the count register. */
4064 int r
= REGNO (count
);
4067 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
4069 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4070 if (i
== r
|| origins
[i
] == r
)
4079 /* The idea behind this optimization is to look for cases where we
4080 move data from A to B to C, and instead move from A to B, and A to
4081 C. If B is a virtual register or memory, this is a big win on its
4082 own. If B turns out to be unneeded after this, it's a bigger win.
4083 For each register, we try to determine where it's value originally
4084 came from, if it's propogated purely through moves (and not
4085 computes). The ORIGINS[] array has the regno for the "origin" of
4086 the value in the [regno] it's indexed by. */
4088 rl78_propogate_register_origins (void)
4090 int origins
[FIRST_PSEUDO_REGISTER
];
4091 int age
[FIRST_PSEUDO_REGISTER
];
4093 rtx_insn
*insn
, *ninsn
= NULL
;
4096 reset_origins (origins
, age
);
4098 for (insn
= get_insns (); insn
; insn
= ninsn
)
4100 ninsn
= next_nonnote_nondebug_insn (insn
);
4104 fprintf (dump_file
, "\n");
4105 fprintf (dump_file
, "Origins:");
4106 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4107 if (origins
[i
] != i
)
4108 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
4109 fprintf (dump_file
, "\n");
4110 print_rtl_single (dump_file
, insn
);
4113 switch (GET_CODE (insn
))
4119 reset_origins (origins
, age
);
4126 pat
= PATTERN (insn
);
4128 if (GET_CODE (pat
) == PARALLEL
)
4130 rtx clobber
= XVECEXP (pat
, 0, 1);
4131 pat
= XVECEXP (pat
, 0, 0);
4132 if (GET_CODE (clobber
) == CLOBBER
4133 && GET_CODE (XEXP (clobber
, 0)) == REG
)
4135 int cr
= REGNO (XEXP (clobber
, 0));
4136 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
4138 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
4139 for (i
= 0; i
< mb
; i
++)
4141 origins
[cr
+ i
] = cr
+ i
;
4145 /* This happens with the DIV patterns. */
4146 else if (GET_CODE (clobber
) == SET
)
4148 set_origin (clobber
, insn
, origins
, age
);
4154 if (GET_CODE (pat
) == SET
)
4156 set_origin (pat
, insn
, origins
, age
);
4158 else if (GET_CODE (pat
) == CLOBBER
4159 && GET_CODE (XEXP (pat
, 0)) == REG
)
4161 if (REG_P (XEXP (pat
, 0)))
4163 unsigned int reg
= REGNO (XEXP (pat
, 0));
4173 /* Remove any SETs where the destination is unneeded. */
4175 rl78_remove_unused_sets (void)
4177 rtx_insn
*insn
, *ninsn
= NULL
;
4180 for (insn
= get_insns (); insn
; insn
= ninsn
)
4182 ninsn
= next_nonnote_nondebug_insn (insn
);
4184 rtx set
= single_set (insn
);
4188 dest
= SET_DEST (set
);
4190 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
4193 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
4196 fprintf (dump_file
, "deleting because the set register is never used.\n");
4202 /* This is the top of the devritualization pass. */
4206 /* split2 only happens when optimizing, but we need all movSIs to be
4211 rl78_alloc_physical_registers ();
4215 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4216 print_rtl_with_bb (dump_file
, get_insns (), 0);
4219 rl78_propogate_register_origins ();
4220 rl78_calculate_death_notes ();
4224 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4225 print_rtl_with_bb (dump_file
, get_insns (), 0);
4226 fprintf (dump_file
, "\n======================================================================\n");
4229 rl78_remove_unused_sets ();
4231 /* The code after devirtualizing has changed so much that at this point
4232 we might as well just rescan everything. Note that
4233 df_rescan_all_insns is not going to help here because it does not
4234 touch the artificial uses and defs. */
4235 df_finish_pass (true);
4237 df_live_add_problem ();
4238 df_scan_alloc (NULL
);
4245 #undef TARGET_RETURN_IN_MEMORY
4246 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4249 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
4251 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
4252 return (size
== -1 || size
> 8);
4256 #undef TARGET_RTX_COSTS
4257 #define TARGET_RTX_COSTS rl78_rtx_costs
4260 rl78_rtx_costs (rtx x
,
4262 int outer_code ATTRIBUTE_UNUSED
,
4263 int opno ATTRIBUTE_UNUSED
,
4265 bool speed ATTRIBUTE_UNUSED
)
4267 int code
= GET_CODE (x
);
4269 if (code
== IF_THEN_ELSE
)
4271 *total
= COSTS_N_INSNS (10);
4277 if (code
== MULT
&& ! speed
)
4279 * total
= COSTS_N_INSNS (8);
4291 /* If we are compiling for space then we do not want to use the
4292 inline SImode multiplication patterns or shift sequences.
4293 The cost is not set to 1 or 5 however as we have to allow for
4294 the possibility that we might be converting a leaf function
4295 into a non-leaf function. (There is no way to tell here).
4296 A value of 13 seems to be a reasonable compromise for the
4298 * total
= COSTS_N_INSNS (13);
4299 else if (RL78_MUL_G14
)
4300 *total
= COSTS_N_INSNS (14);
4301 else if (RL78_MUL_G13
)
4302 *total
= COSTS_N_INSNS (29);
4304 *total
= COSTS_N_INSNS (500);
4308 *total
= COSTS_N_INSNS (8);
4314 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4316 switch (INTVAL (XEXP (x
, 1)))
4318 case 0: *total
= COSTS_N_INSNS (0); break;
4319 case 1: *total
= COSTS_N_INSNS (6); break;
4320 case 2: case 3: case 4: case 5: case 6: case 7:
4321 *total
= COSTS_N_INSNS (10); break;
4322 case 8: *total
= COSTS_N_INSNS (6); break;
4323 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4324 *total
= COSTS_N_INSNS (10); break;
4325 case 16: *total
= COSTS_N_INSNS (3); break;
4326 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4327 *total
= COSTS_N_INSNS (4); break;
4328 case 24: *total
= COSTS_N_INSNS (4); break;
4329 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4330 *total
= COSTS_N_INSNS (5); break;
4334 *total
= COSTS_N_INSNS (10+4*16);
4345 static GTY(()) section
* saddr_section
;
4346 static GTY(()) section
* frodata_section
;
4349 rl78_saddr_p (rtx x
)
4355 if (GET_CODE (x
) == PLUS
)
4357 if (GET_CODE (x
) != SYMBOL_REF
)
4361 if (memcmp (c
, "@s.", 3) == 0)
4372 if (GET_CODE (x
) != CONST_INT
)
4375 if ((INTVAL (x
) & 0xFF00) != 0xFF00)
4381 #undef TARGET_STRIP_NAME_ENCODING
4382 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4385 rl78_strip_name_encoding (const char * sym
)
4391 else if (*sym
== '@' && sym
[2] == '.')
4398 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4399 is important if the stripped name is going to be passed to assemble_name()
4400 as that handles asterisk prefixed names in a special manner. */
4403 rl78_strip_nonasm_name_encoding (const char * sym
)
4407 if (*sym
== '@' && sym
[2] == '.')
4416 rl78_attrlist_to_encoding (tree list
, tree decl ATTRIBUTE_UNUSED
)
4420 if (is_attribute_p ("saddr", TREE_PURPOSE (list
)))
4422 list
= TREE_CHAIN (list
);
4428 #define RL78_ATTRIBUTES(decl) \
4429 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4430 : DECL_ATTRIBUTES (decl) \
4431 ? (DECL_ATTRIBUTES (decl)) \
4432 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4434 #undef TARGET_ENCODE_SECTION_INFO
4435 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4438 rl78_encode_section_info (tree decl
, rtx rtl
, int first
)
4441 const char * oldname
;
4446 tree rl78_attributes
;
4451 rtlname
= XEXP (rtl
, 0);
4453 if (GET_CODE (rtlname
) == SYMBOL_REF
)
4454 oldname
= XSTR (rtlname
, 0);
4455 else if (GET_CODE (rtlname
) == MEM
4456 && GET_CODE (XEXP (rtlname
, 0)) == SYMBOL_REF
)
4457 oldname
= XSTR (XEXP (rtlname
, 0), 0);
4461 type
= TREE_TYPE (decl
);
4462 if (type
== error_mark_node
)
4464 if (! DECL_P (decl
))
4466 rl78_attributes
= RL78_ATTRIBUTES (decl
);
4468 encoding
= rl78_attrlist_to_encoding (rl78_attributes
, decl
);
4472 newname
= (char *) alloca (strlen (oldname
) + 4);
4473 sprintf (newname
, "@%c.%s", encoding
, oldname
);
4474 idp
= get_identifier (newname
);
4476 gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (idp
));
4477 SYMBOL_REF_WEAK (XEXP (rtl
, 0)) = DECL_WEAK (decl
);
4478 SET_SYMBOL_REF_DECL (XEXP (rtl
, 0), decl
);
4482 #undef TARGET_ASM_INIT_SECTIONS
4483 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4486 rl78_asm_init_sections (void)
4489 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4490 "\t.section .saddr,\"aw\",@progbits");
4492 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4493 "\t.section .frodata,\"aw\",@progbits");
4496 #undef TARGET_ASM_SELECT_SECTION
4497 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4500 rl78_select_section (tree decl
,
4502 unsigned HOST_WIDE_INT align
)
4506 switch (TREE_CODE (decl
))
4509 if (!TREE_READONLY (decl
)
4510 || TREE_SIDE_EFFECTS (decl
)
4511 || !DECL_INITIAL (decl
)
4512 || (DECL_INITIAL (decl
) != error_mark_node
4513 && !TREE_CONSTANT (DECL_INITIAL (decl
))))
4517 if (! TREE_CONSTANT (decl
))
4525 if (TREE_CODE (decl
) == VAR_DECL
)
4527 const char *name
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
4529 if (name
[0] == '@' && name
[2] == '.')
4533 return saddr_section
;
4536 if (TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_FAR
4539 return frodata_section
;
4544 return TARGET_ES0
? frodata_section
: readonly_data_section
;
4546 switch (categorize_decl_for_section (decl
, reloc
))
4548 case SECCAT_TEXT
: return text_section
;
4549 case SECCAT_DATA
: return data_section
;
4550 case SECCAT_BSS
: return bss_section
;
4551 case SECCAT_RODATA
: return TARGET_ES0
? frodata_section
: readonly_data_section
;
4553 return default_select_section (decl
, reloc
, align
);
4558 rl78_output_labelref (FILE *file
, const char *str
)
4562 str2
= targetm
.strip_name_encoding (str
);
4564 fputs (user_label_prefix
, file
);
4569 rl78_output_aligned_common (FILE *stream
,
4570 tree decl ATTRIBUTE_UNUSED
,
4572 int size
, int align
, int global
)
4574 /* We intentionally don't use rl78_section_tag() here. */
4575 if (name
[0] == '@' && name
[2] == '.')
4577 const char *sec
= 0;
4581 switch_to_section (saddr_section
);
4590 while (align
> BITS_PER_UNIT
)
4595 name2
= targetm
.strip_name_encoding (name
);
4597 fprintf (stream
, "\t.global\t_%s\n", name2
);
4598 fprintf (stream
, "\t.p2align %d\n", p2align
);
4599 fprintf (stream
, "\t.type\t_%s,@object\n", name2
);
4600 fprintf (stream
, "\t.size\t_%s,%d\n", name2
, size
);
4601 fprintf (stream
, "_%s:\n\t.zero\t%d\n", name2
, size
);
4608 fprintf (stream
, "\t.local\t");
4609 assemble_name (stream
, name
);
4610 fprintf (stream
, "\n");
4612 fprintf (stream
, "\t.comm\t");
4613 assemble_name (stream
, name
);
4614 fprintf (stream
, ",%u,%u\n", size
, align
/ BITS_PER_UNIT
);
4617 #undef TARGET_INSERT_ATTRIBUTES
4618 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4621 rl78_insert_attributes (tree decl
, tree
*attributes ATTRIBUTE_UNUSED
)
4624 && TREE_CODE (decl
) == VAR_DECL
4625 && TREE_READONLY (decl
)
4626 && TREE_ADDRESSABLE (decl
)
4627 && TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_GENERIC
)
4629 tree type
= TREE_TYPE (decl
);
4630 tree attr
= TYPE_ATTRIBUTES (type
);
4631 int q
= TYPE_QUALS_NO_ADDR_SPACE (type
) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR
);
4633 TREE_TYPE (decl
) = build_type_attribute_qual_variant (type
, attr
, q
);
4637 #undef TARGET_ASM_INTEGER
4638 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4641 rl78_asm_out_integer (rtx x
, unsigned int size
, int aligned_p
)
4643 if (default_assemble_integer (x
, size
, aligned_p
))
4648 assemble_integer_with_op (".long\t", x
);
4655 #undef TARGET_UNWIND_WORD_MODE
4656 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4658 static scalar_int_mode
4659 rl78_unwind_word_mode (void)
4664 #ifndef USE_COLLECT2
4665 #undef TARGET_ASM_CONSTRUCTOR
4666 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4667 #undef TARGET_ASM_DESTRUCTOR
4668 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4671 rl78_asm_ctor_dtor (rtx symbol
, int priority
, bool is_ctor
)
4675 if (priority
!= DEFAULT_INIT_PRIORITY
)
4677 /* This section of the function is based upon code copied
4678 from: gcc/varasm.c:get_cdtor_priority_section(). */
4681 sprintf (buf
, "%s.%.5u", is_ctor
? ".ctors" : ".dtors",
4682 MAX_INIT_PRIORITY
- priority
);
4683 sec
= get_section (buf
, 0, NULL
);
4686 sec
= is_ctor
? ctors_section
: dtors_section
;
4688 assemble_addr_to_section (symbol
, sec
);
4692 rl78_asm_constructor (rtx symbol
, int priority
)
4694 rl78_asm_ctor_dtor (symbol
, priority
, true);
4698 rl78_asm_destructor (rtx symbol
, int priority
)
4700 rl78_asm_ctor_dtor (symbol
, priority
, false);
4702 #endif /* ! USE_COLLECT2 */
4704 /* Scan backwards through the insn chain looking to see if the flags
4705 have been set for a comparison of OP against OPERAND. Start with
4706 the insn *before* the current insn. */
4709 rl78_flags_already_set (rtx op
, rtx operand
)
4711 /* We only track the Z flag. */
4712 if (GET_CODE (op
) != EQ
&& GET_CODE (op
) != NE
)
4715 /* This should not happen, but let's be paranoid. */
4716 if (current_output_insn
== NULL_RTX
)
4722 for (insn
= prev_nonnote_nondebug_insn (current_output_insn
);
4724 insn
= prev_nonnote_nondebug_insn (insn
))
4729 if (! INSN_P (insn
))
4732 /* Make sure that the insn can be recognized. */
4733 if (recog_memoized (insn
) == -1)
4736 enum attr_update_Z updated
= get_attr_update_Z (insn
);
4738 rtx set
= single_set (insn
);
4739 bool must_break
= (set
!= NULL_RTX
&& rtx_equal_p (operand
, SET_DEST (set
)));
4745 case UPDATE_Z_CLOBBER
:
4748 case UPDATE_Z_UPDATE_Z
:
4760 /* We have to re-recognize the current insn as the call(s) to
4761 get_attr_update_Z() above will have overwritten the recog_data cache. */
4762 recog_memoized (current_output_insn
);
4763 cleanup_subreg_operands (current_output_insn
);
4764 constrain_operands_cached (current_output_insn
, 1);
4770 rl78_addsi3_internal (rtx
* operands
, unsigned int alternative
)
4772 /* If we are adding in a constant symbolic address when -mes0
4773 is active then we know that the address must be <64K and
4774 that it is invalid to access anything above 64K relative to
4775 this address. So we can skip adding in the high bytes. */
4777 && GET_CODE (operands
[2]) == SYMBOL_REF
4778 && TREE_CODE (SYMBOL_REF_DECL (operands
[2])) == VAR_DECL
4779 && TREE_READONLY (SYMBOL_REF_DECL (operands
[2]))
4780 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands
[2])))
4781 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
4783 switch (alternative
)
4787 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax";
4789 return "movw ax, %h1\n\taddw ax,%h2\n\tmovw bc, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax\n\tmovw ax, bc\n\tmovw %h0, ax";
4796 rl78_emit_libcall (const char *name
, enum rtx_code code
,
4797 enum machine_mode dmode
, enum machine_mode smode
,
4798 int noperands
, rtx
*operands
)
4806 libcall
= gen_rtx_SYMBOL_REF (Pmode
, name
);
4811 ret
= emit_library_call_value (libcall
, NULL_RTX
, LCT_CONST
,
4812 dmode
, operands
[1], smode
);
4813 equiv
= gen_rtx_fmt_e (code
, dmode
, operands
[1]);
4817 ret
= emit_library_call_value (libcall
, NULL_RTX
,
4819 operands
[1], smode
, operands
[2],
4821 equiv
= gen_rtx_fmt_ee (code
, dmode
, operands
[1], operands
[2]);
4828 insns
= get_insns ();
4830 emit_libcall_block (insns
, operands
[0], ret
, equiv
);
4835 #undef TARGET_PREFERRED_RELOAD_CLASS
4836 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4839 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t rclass
)
4841 if (rclass
== NO_REGS
)
4848 struct gcc_target targetm
= TARGET_INITIALIZER
;
4850 #include "gt-rl78.h"