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"
35 #include "diagnostic-core.h"
37 #include "stor-layout.h"
40 #include "insn-attr.h"
45 #include "langhooks.h"
46 #include "tree-pass.h"
48 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
51 /* This file should be included last. */
52 #include "target-def.h"
54 static inline bool is_interrupt_func (const_tree decl
);
55 static inline bool is_brk_interrupt_func (const_tree decl
);
56 static void rl78_reorg (void);
57 static const char *rl78_strip_name_encoding (const char *);
58 static const char *rl78_strip_nonasm_name_encoding (const char *);
59 static section
* rl78_select_section (tree
, int, unsigned HOST_WIDE_INT
);
62 /* Debugging statements are tagged with DEBUG0 only so that they can
63 be easily enabled individually, by replacing the '0' with '1' as
68 /* REGISTER_NAMES has the names for individual 8-bit registers, but
69 these have the names we need to use when referring to 16-bit
71 static const char * const word_regnames
[] =
73 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
74 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
75 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
76 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
77 "sp", "ap", "psw", "es", "cs"
80 /* Structure for G13 MDUC registers. */
84 enum machine_mode mode
;
87 struct mduc_reg_type mduc_regs
[] =
97 struct GTY(()) machine_function
99 /* If set, the rest of the fields have been computed. */
101 /* Which register pairs need to be pushed in the prologue. */
102 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
104 /* These fields describe the frame layout... */
106 /* 4 bytes for saved PC */
109 int framesize_locals
;
110 int framesize_outgoing
;
114 /* If set, recog is allowed to match against the "real" patterns. */
116 /* If set, recog is allowed to match against the "virtual" patterns. */
118 /* Set if the current function needs to clean up any trampolines. */
119 int trampolines_used
;
120 /* True if the ES register is used and hence
121 needs to be saved inside interrupt handlers. */
125 /* This is our init_machine_status, as set in
126 rl78_option_override. */
127 static struct machine_function
*
128 rl78_init_machine_status (void)
130 struct machine_function
*m
;
132 m
= ggc_cleared_alloc
<machine_function
> ();
133 m
->virt_insns_ok
= 1;
138 /* This pass converts virtual instructions using virtual registers, to
139 real instructions using real registers. Rather than run it as
140 reorg, we reschedule it before vartrack to help with debugging. */
143 const pass_data pass_data_rl78_devirt
=
147 OPTGROUP_NONE
, /* optinfo_flags */
148 TV_MACH_DEP
, /* tv_id */
149 0, /* properties_required */
150 0, /* properties_provided */
151 0, /* properties_destroyed */
152 0, /* todo_flags_start */
153 0, /* todo_flags_finish */
156 class pass_rl78_devirt
: public rtl_opt_pass
159 pass_rl78_devirt (gcc::context
*ctxt
)
160 : rtl_opt_pass (pass_data_rl78_devirt
, ctxt
)
164 /* opt_pass methods: */
165 virtual unsigned int execute (function
*)
174 make_pass_rl78_devirt (gcc::context
*ctxt
)
176 return new pass_rl78_devirt (ctxt
);
179 /* Redundant move elimination pass. Must be run after the basic block
180 reordering pass for the best effect. */
183 move_elim_pass (void)
185 rtx_insn
*insn
, *ninsn
;
188 for (insn
= get_insns (); insn
; insn
= ninsn
)
192 ninsn
= next_nonnote_nondebug_insn (insn
);
194 if ((set
= single_set (insn
)) == NULL_RTX
)
200 /* If we have two SET insns in a row (without anything
201 between them) and the source of the second one is the
202 destination of the first one, and vice versa, then we
203 can eliminate the second SET. */
205 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
206 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
207 /* ... and none of the operands are volatile. */
208 && ! volatile_refs_p (SET_SRC (prev
))
209 && ! volatile_refs_p (SET_DEST (prev
))
210 && ! volatile_refs_p (SET_SRC (set
))
211 && ! volatile_refs_p (SET_DEST (set
)))
214 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
225 print_rtl_with_bb (dump_file
, get_insns (), 0);
232 const pass_data pass_data_rl78_move_elim
=
235 "move_elim", /* name */
236 OPTGROUP_NONE
, /* optinfo_flags */
237 TV_MACH_DEP
, /* tv_id */
238 0, /* properties_required */
239 0, /* properties_provided */
240 0, /* properties_destroyed */
241 0, /* todo_flags_start */
242 0, /* todo_flags_finish */
245 class pass_rl78_move_elim
: public rtl_opt_pass
248 pass_rl78_move_elim (gcc::context
*ctxt
)
249 : rtl_opt_pass (pass_data_rl78_move_elim
, ctxt
)
253 /* opt_pass methods: */
254 virtual unsigned int execute (function
*) { return move_elim_pass (); }
259 make_pass_rl78_move_elim (gcc::context
*ctxt
)
261 return new pass_rl78_move_elim (ctxt
);
264 #undef TARGET_ASM_FILE_START
265 #define TARGET_ASM_FILE_START rl78_asm_file_start
268 rl78_asm_file_start (void)
274 /* The memory used is 0xffec8 to 0xffedf; real registers are in
275 0xffee0 to 0xffee7. */
276 for (i
= 8; i
< 32; i
++)
277 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
281 for (i
= 0; i
< 8; i
++)
283 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
284 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
285 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
289 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
290 struct register_pass_info rl78_devirt_info
=
295 PASS_POS_INSERT_BEFORE
298 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
299 struct register_pass_info rl78_move_elim_info
=
304 PASS_POS_INSERT_AFTER
307 register_pass (& rl78_devirt_info
);
308 register_pass (& rl78_move_elim_info
);
312 rl78_output_symbol_ref (FILE * file
, rtx sym
)
314 tree type
= SYMBOL_REF_DECL (sym
);
315 const char *str
= XSTR (sym
, 0);
319 fputs (str
+ 1, file
);
323 str
= rl78_strip_nonasm_name_encoding (str
);
324 if (type
&& TREE_CODE (type
) == FUNCTION_DECL
)
326 fprintf (file
, "%%code(");
327 assemble_name (file
, str
);
331 assemble_name (file
, str
);
335 #undef TARGET_OPTION_OVERRIDE
336 #define TARGET_OPTION_OVERRIDE rl78_option_override
338 #define MUST_SAVE_MDUC_REGISTERS \
339 (TARGET_SAVE_MDUC_REGISTERS \
340 && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
343 rl78_option_override (void)
345 flag_omit_frame_pointer
= 1;
346 flag_no_function_cse
= 1;
347 flag_split_wide_types
= 0;
349 init_machine_status
= rl78_init_machine_status
;
355 for (i
= 24; i
< 32; i
++)
360 && strcmp (lang_hooks
.name
, "GNU C")
361 && strcmp (lang_hooks
.name
, "GNU C11")
362 && strcmp (lang_hooks
.name
, "GNU C89")
363 && strcmp (lang_hooks
.name
, "GNU C99")
364 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
365 && strcmp (lang_hooks
.name
, "GNU GIMPLE"))
366 /* Address spaces are currently only supported by C. */
367 error ("-mes0 can only be used with C");
369 if (TARGET_SAVE_MDUC_REGISTERS
&& !(TARGET_G13
|| RL78_MUL_G13
))
370 warning (0, "mduc registers only saved for G13 target");
372 switch (rl78_cpu_type
)
375 rl78_cpu_type
= CPU_G14
;
376 if (rl78_mul_type
== MUL_UNINIT
)
377 rl78_mul_type
= MUL_NONE
;
381 switch (rl78_mul_type
)
383 case MUL_UNINIT
: rl78_mul_type
= MUL_NONE
; break;
384 case MUL_NONE
: break;
385 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
386 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
391 switch (rl78_mul_type
)
393 case MUL_UNINIT
: rl78_mul_type
= MUL_G13
; break;
394 case MUL_NONE
: break;
396 /* The S2 core does not have mul/div instructions. */
397 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
402 switch (rl78_mul_type
)
404 case MUL_UNINIT
: rl78_mul_type
= MUL_G14
; break;
405 case MUL_NONE
: break;
407 /* The G14 core does not have the hardware multiply peripheral used by the
408 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
409 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
415 /* Most registers are 8 bits. Some are 16 bits because, for example,
416 gcc doesn't like dealing with $FP as a register pair (the second
417 half of $fp is also 2 to keep reload happy wrt register pairs, but
418 no register class includes it). This table maps register numbers
420 static const int register_sizes
[] =
422 1, 1, 1, 1, 1, 1, 1, 1,
423 1, 1, 1, 1, 1, 1, 1, 1,
424 1, 1, 1, 1, 1, 1, 2, 2,
425 1, 1, 1, 1, 1, 1, 1, 1,
429 /* Predicates used in the MD patterns. This one is true when virtual
430 insns may be matched, which typically means before (or during) the
433 rl78_virt_insns_ok (void)
436 return cfun
->machine
->virt_insns_ok
;
440 /* Predicates used in the MD patterns. This one is true when real
441 insns may be matched, which typically means after (or during) the
444 rl78_real_insns_ok (void)
447 return cfun
->machine
->real_insns_ok
;
451 /* Implements HARD_REGNO_NREGS. */
453 rl78_hard_regno_nregs (int regno
, machine_mode mode
)
455 int rs
= register_sizes
[regno
];
458 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
461 /* Implements HARD_REGNO_MODE_OK. */
463 rl78_hard_regno_mode_ok (int regno
, machine_mode mode
)
465 int s
= GET_MODE_SIZE (mode
);
469 /* These are not to be used by gcc. */
470 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
472 /* $fp can always be accessed as a 16-bit value. */
473 if (regno
== FP_REG
&& s
== 2)
477 /* Since a reg-reg move is really a reg-mem move, we must
478 enforce alignment. */
479 if (s
> 1 && (regno
% 2))
484 return (mode
== BImode
);
485 /* All other registers must be accessed in their natural sizes. */
486 if (s
== register_sizes
[regno
])
491 /* Simplify_gen_subreg() doesn't handle memory references the way we
492 need it to below, so we use this function for when we must get a
493 valid subreg in a "natural" state. */
495 rl78_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
497 if (GET_CODE (r
) == MEM
)
498 return adjust_address (r
, mode
, byte
);
500 return simplify_gen_subreg (mode
, r
, omode
, byte
);
503 /* Used by movsi. Split SImode moves into two HImode moves, using
504 appropriate patterns for the upper and lower halves of symbols. */
506 rl78_expand_movsi (rtx
*operands
)
508 rtx op00
, op02
, op10
, op12
;
510 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
511 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
512 if (GET_CODE (operands
[1]) == CONST
513 || GET_CODE (operands
[1]) == SYMBOL_REF
)
515 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
516 op10
= gen_rtx_CONST (HImode
, op10
);
517 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
518 op12
= gen_rtx_CONST (HImode
, op12
);
522 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
523 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
526 if (rtx_equal_p (operands
[0], operands
[1]))
528 else if (rtx_equal_p (op00
, op12
))
530 emit_move_insn (op02
, op12
);
531 emit_move_insn (op00
, op10
);
535 emit_move_insn (op00
, op10
);
536 emit_move_insn (op02
, op12
);
540 /* Generate code to move an SImode value. */
542 rl78_split_movsi (rtx
*operands
, enum machine_mode omode
)
544 rtx op00
, op02
, op10
, op12
;
546 op00
= rl78_subreg (HImode
, operands
[0], omode
, 0);
547 op02
= rl78_subreg (HImode
, operands
[0], omode
, 2);
549 if (GET_CODE (operands
[1]) == CONST
550 || GET_CODE (operands
[1]) == SYMBOL_REF
)
552 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
553 op10
= gen_rtx_CONST (HImode
, op10
);
554 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
555 op12
= gen_rtx_CONST (HImode
, op12
);
559 op10
= rl78_subreg (HImode
, operands
[1], omode
, 0);
560 op12
= rl78_subreg (HImode
, operands
[1], omode
, 2);
563 if (rtx_equal_p (operands
[0], operands
[1]))
565 else if (rtx_equal_p (op00
, op12
))
581 /* Used by various two-operand expanders which cannot accept all
582 operands in the "far" namespace. Force some such operands into
583 registers so that each pattern has at most one far operand. */
585 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
590 /* FIXME: in the future, be smarter about only doing this if the
591 other operand is also far, assuming the devirtualizer can also
593 if (rl78_far_p (operands
[0]))
595 temp_reg
= operands
[0];
596 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
602 emit_insn (gen (operands
[0], operands
[1]));
604 emit_move_insn (temp_reg
, operands
[0]);
608 /* Likewise, but for three-operand expanders. */
610 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
615 /* FIXME: Likewise. */
616 if (rl78_far_p (operands
[1]))
618 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
619 emit_move_insn (temp_reg
, operands
[1]);
620 operands
[1] = temp_reg
;
623 if (rl78_far_p (operands
[0]))
625 temp_reg
= operands
[0];
626 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
632 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
634 emit_move_insn (temp_reg
, operands
[0]);
639 rl78_one_far_p (rtx
*operands
, int n
)
644 for (i
= 0; i
< n
; i
++)
645 if (rl78_far_p (operands
[i
]))
649 else if (rtx_equal_p (operands
[i
], which
))
656 #undef TARGET_CAN_ELIMINATE
657 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
660 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
665 /* Returns true if the given register needs to be saved by the
668 need_to_save (unsigned int regno
)
670 if (is_interrupt_func (cfun
->decl
))
672 /* We don't know what devirt will need */
676 /* We don't need to save registers that have
677 been reserved for interrupt handlers. */
681 /* If the handler is a non-leaf function then it may call
682 non-interrupt aware routines which will happily clobber
683 any call_used registers, so we have to preserve them.
684 We do not have to worry about the frame pointer register
685 though, as that is handled below. */
686 if (!crtl
->is_leaf
&& call_used_regs
[regno
] && regno
< 22)
689 /* Otherwise we only have to save a register, call_used
690 or not, if it is used by this handler. */
691 return df_regs_ever_live_p (regno
);
694 if (regno
== FRAME_POINTER_REGNUM
695 && (frame_pointer_needed
|| df_regs_ever_live_p (regno
)))
697 if (fixed_regs
[regno
])
699 if (crtl
->calls_eh_return
)
701 if (df_regs_ever_live_p (regno
)
702 && !call_used_regs
[regno
])
707 /* We use this to wrap all emitted insns in the prologue. */
711 RTX_FRAME_RELATED_P (x
) = 1;
715 /* Compute all the frame-related fields in our machine_function
718 rl78_compute_frame_info (void)
722 cfun
->machine
->computed
= 1;
723 cfun
->machine
->framesize_regs
= 0;
724 cfun
->machine
->framesize_locals
= get_frame_size ();
725 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
727 for (i
= 0; i
< 16; i
++)
728 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
730 cfun
->machine
->need_to_push
[i
] = 1;
731 cfun
->machine
->framesize_regs
+= 2;
734 cfun
->machine
->need_to_push
[i
] = 0;
736 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
737 cfun
->machine
->framesize_locals
++;
739 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
740 + cfun
->machine
->framesize_locals
741 + cfun
->machine
->framesize_outgoing
);
744 /* Returns true if the provided function has the specified attribute. */
746 has_func_attr (const_tree decl
, const char * func_attr
)
748 if (decl
== NULL_TREE
)
749 decl
= current_function_decl
;
751 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
754 /* Returns true if the provided function has the "interrupt" attribute. */
756 is_interrupt_func (const_tree decl
)
758 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
761 /* Returns true if the provided function has the "brk_interrupt" attribute. */
763 is_brk_interrupt_func (const_tree decl
)
765 return has_func_attr (decl
, "brk_interrupt");
768 /* Check "interrupt" attributes. */
770 rl78_handle_func_attribute (tree
* node
,
773 int flags ATTRIBUTE_UNUSED
,
776 gcc_assert (DECL_P (* node
));
777 gcc_assert (args
== NULL_TREE
);
779 if (TREE_CODE (* node
) != FUNCTION_DECL
)
781 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
783 * no_add_attrs
= true;
786 /* FIXME: We ought to check that the interrupt and exception
787 handler attributes have been applied to void functions. */
791 /* Check "naked" attributes. */
793 rl78_handle_naked_attribute (tree
* node
,
794 tree name ATTRIBUTE_UNUSED
,
796 int flags ATTRIBUTE_UNUSED
,
799 gcc_assert (DECL_P (* node
));
800 gcc_assert (args
== NULL_TREE
);
802 if (TREE_CODE (* node
) != FUNCTION_DECL
)
804 warning (OPT_Wattributes
, "naked attribute only applies to functions");
805 * no_add_attrs
= true;
808 /* Disable warnings about this function - eg reaching the end without
809 seeing a return statement - because the programmer is doing things
810 that gcc does not know about. */
811 TREE_NO_WARNING (* node
) = 1;
816 /* Check "saddr" attributes. */
818 rl78_handle_saddr_attribute (tree
* node
,
820 tree args ATTRIBUTE_UNUSED
,
821 int flags ATTRIBUTE_UNUSED
,
824 gcc_assert (DECL_P (* node
));
826 if (TREE_CODE (* node
) == FUNCTION_DECL
)
828 warning (OPT_Wattributes
, "%qE attribute doesn't apply to functions",
830 * no_add_attrs
= true;
836 #undef TARGET_ATTRIBUTE_TABLE
837 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
839 /* Table of RL78-specific attributes. */
840 const struct attribute_spec rl78_attribute_table
[] =
842 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
843 affects_type_identity. */
844 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
846 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
848 { "naked", 0, 0, true, false, false, rl78_handle_naked_attribute
,
850 { "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute
,
852 { NULL
, 0, 0, false, false, false, NULL
, false }
857 /* Break down an address RTX into its component base/index/addend
858 portions and return TRUE if the address is of a valid form, else
861 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
867 if (GET_CODE (x
) == UNSPEC
868 && XINT (x
, 1) == UNS_ES_ADDR
)
869 x
= XVECEXP (x
, 0, 1);
871 if (GET_CODE (x
) == REG
)
877 /* We sometimes get these without the CONST wrapper */
878 if (GET_CODE (x
) == PLUS
879 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
880 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
886 if (GET_CODE (x
) == PLUS
)
891 if (GET_CODE (*base
) == SUBREG
)
893 if (GET_MODE (*base
) == HImode
894 && GET_MODE (XEXP (*base
, 0)) == SImode
895 && GET_CODE (XEXP (*base
, 0)) == REG
)
897 /* This is a throw-away rtx just to tell everyone
898 else what effective register we're using. */
899 *base
= gen_rtx_REG (HImode
, REGNO (XEXP (*base
, 0)));
903 if (GET_CODE (*base
) != REG
904 && GET_CODE (x
) == REG
)
911 if (GET_CODE (*base
) != REG
)
914 if (GET_CODE (x
) == ZERO_EXTEND
915 && GET_CODE (XEXP (x
, 0)) == REG
)
917 *index
= XEXP (x
, 0);
922 switch (GET_CODE (x
))
925 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
926 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
937 switch (GET_CODE (XEXP (x
, 0)))
961 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
964 rl78_hl_b_c_addr_p (rtx op
)
968 if (GET_CODE (op
) != PLUS
)
972 if (GET_CODE (hl
) == ZERO_EXTEND
)
978 if (GET_CODE (hl
) != REG
)
980 if (GET_CODE (bc
) != ZERO_EXTEND
)
983 if (GET_CODE (bc
) != REG
)
985 if (REGNO (hl
) != HL_REG
)
987 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
993 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
995 /* Return the appropriate mode for a named address address. */
997 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
998 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
1000 static enum machine_mode
1001 rl78_addr_space_address_mode (addr_space_t addrspace
)
1005 case ADDR_SPACE_GENERIC
:
1007 case ADDR_SPACE_NEAR
:
1009 case ADDR_SPACE_FAR
:
1016 /* Used in various constraints and predicates to match operands in the
1017 "far" address space. */
1024 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx (x
);
1025 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
1028 /* Not all far addresses are legitimate, because the devirtualizer
1029 can't handle them. */
1030 if (! rl78_as_legitimate_address (GET_MODE (x
), XEXP (x
, 0), false, ADDR_SPACE_FAR
))
1033 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x
))) == 32;
1036 /* Return the appropriate mode for a named address pointer. */
1037 #undef TARGET_ADDR_SPACE_POINTER_MODE
1038 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1041 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
1045 case ADDR_SPACE_GENERIC
:
1047 case ADDR_SPACE_NEAR
:
1049 case ADDR_SPACE_FAR
:
1056 /* Returns TRUE for valid addresses. */
1057 #undef TARGET_VALID_POINTER_MODE
1058 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1061 rl78_valid_pointer_mode (machine_mode m
)
1063 return (m
== HImode
|| m
== SImode
);
1066 #undef TARGET_LEGITIMATE_CONSTANT_P
1067 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1070 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
1076 #define TARGET_LRA_P hook_bool_void_false
1078 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1079 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1082 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
1083 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
1085 rtx base
, index
, addend
;
1086 bool is_far_addr
= false;
1089 as_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (as
));
1091 if (GET_CODE (x
) == UNSPEC
1092 && XINT (x
, 1) == UNS_ES_ADDR
)
1094 x
= XVECEXP (x
, 0, 1);
1098 if (as_bits
== 16 && is_far_addr
)
1101 if (! characterize_address (x
, &base
, &index
, &addend
))
1104 /* We can't extract the high/low portions of a PLUS address
1105 involving a register during devirtualization, so make sure all
1106 such __far addresses do not have addends. This forces GCC to do
1107 the sum separately. */
1108 if (addend
&& base
&& as_bits
== 32 && GET_MODE (base
) == SImode
)
1113 int ir
= REGNO (index
);
1114 int br
= REGNO (base
);
1116 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1117 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
1118 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
1122 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
1125 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
1126 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
1132 /* Determine if one named address space is a subset of another. */
1133 #undef TARGET_ADDR_SPACE_SUBSET_P
1134 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1137 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1142 subset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset
));
1143 superset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset
));
1145 return (subset_bits
<= superset_bits
);
1148 #undef TARGET_ADDR_SPACE_CONVERT
1149 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1151 /* Convert from one address space to another. */
1153 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1155 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1156 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1161 to_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as
));
1162 from_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as
));
1164 if (to_bits
< from_bits
)
1167 /* This is unpredictable, as we're truncating off usable address
1170 warning (OPT_Waddress
, "converting far pointer to near pointer");
1171 result
= gen_reg_rtx (HImode
);
1172 if (GET_CODE (op
) == SYMBOL_REF
1173 || (GET_CODE (op
) == REG
&& REGNO (op
) >= FIRST_PSEUDO_REGISTER
))
1174 tmp
= gen_rtx_raw_SUBREG (HImode
, op
, 0);
1176 tmp
= simplify_subreg (HImode
, op
, SImode
, 0);
1177 gcc_assert (tmp
!= NULL_RTX
);
1178 emit_move_insn (result
, tmp
);
1181 else if (to_bits
> from_bits
)
1183 /* This always works. */
1184 result
= gen_reg_rtx (SImode
);
1185 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
1186 if (TREE_CODE (from_type
) == POINTER_TYPE
1187 && TREE_CODE (TREE_TYPE (from_type
)) == FUNCTION_TYPE
)
1188 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
1190 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), GEN_INT (0x0f));
1198 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1200 rl78_regno_mode_code_ok_for_base_p (int regno
, machine_mode mode ATTRIBUTE_UNUSED
,
1201 addr_space_t address_space ATTRIBUTE_UNUSED
,
1202 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
1204 if (regno
<= SP_REG
&& regno
>= 16)
1206 if (index_code
== REG
)
1207 return (regno
== HL_REG
);
1208 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
1213 /* Implements MODE_CODE_BASE_REG_CLASS. */
1215 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED
,
1216 addr_space_t address_space ATTRIBUTE_UNUSED
,
1217 int outer_code ATTRIBUTE_UNUSED
,
1218 int index_code ATTRIBUTE_UNUSED
)
1223 /* Typical stack layout should looks like this after the function's prologue:
1228 | | arguments saved | Increasing
1229 | | on the stack | addresses
1230 PARENT arg pointer -> | | /
1231 -------------------------- ---- -------------------
1232 CHILD |ret | return address
1237 frame pointer -> | | /
1245 | | outgoing | Decreasing
1246 | | arguments | addresses
1247 current stack pointer -> | | / |
1248 -------------------------- ---- ------------------ V
1251 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1252 described in the machine_Function struct definition, above. */
1254 rl78_initial_elimination_offset (int from
, int to
)
1256 int rv
= 0; /* as if arg to arg */
1258 rl78_compute_frame_info ();
1262 case STACK_POINTER_REGNUM
:
1263 rv
+= cfun
->machine
->framesize_outgoing
;
1264 rv
+= cfun
->machine
->framesize_locals
;
1266 case FRAME_POINTER_REGNUM
:
1267 rv
+= cfun
->machine
->framesize_regs
;
1276 case FRAME_POINTER_REGNUM
:
1278 rv
-= cfun
->machine
->framesize_regs
;
1279 case ARG_POINTER_REGNUM
:
1289 rl78_is_naked_func (void)
1291 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1294 /* Check if the block uses mul/div insns for G13 target. */
1297 check_mduc_usage (void)
1302 FOR_EACH_BB_FN (bb
, cfun
)
1304 FOR_BB_INSNS (bb
, insn
)
1307 && (get_attr_is_g13_muldiv_insn (insn
) == IS_G13_MULDIV_INSN_YES
))
1314 /* Expand the function prologue (from the prologue pattern). */
1317 rl78_expand_prologue (void)
1320 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1321 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1324 if (rl78_is_naked_func ())
1327 /* Always re-compute the frame info - the register usage may have changed. */
1328 rl78_compute_frame_info ();
1330 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1331 cfun
->machine
->framesize
+= ARRAY_SIZE (mduc_regs
) * 2;
1333 if (flag_stack_usage_info
)
1334 current_function_static_stack_size
= cfun
->machine
->framesize
;
1336 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1337 for (i
= 0; i
< 4; i
++)
1338 if (cfun
->machine
->need_to_push
[i
])
1340 /* Select Bank 0 if we are using any registers from Bank 0. */
1341 emit_insn (gen_sel_rb (GEN_INT (0)));
1345 for (i
= 0; i
< 16; i
++)
1346 if (cfun
->machine
->need_to_push
[i
])
1354 emit_move_insn (ax
, gen_rtx_REG (HImode
, reg
));
1360 int need_bank
= i
/4;
1362 if (need_bank
!= rb
)
1364 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1369 F (emit_insn (gen_push (gen_rtx_REG (HImode
, reg
))));
1373 emit_insn (gen_sel_rb (GEN_INT (0)));
1375 /* Save ES register inside interrupt functions if it is used. */
1376 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1378 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode
, A_REG
)));
1379 F (emit_insn (gen_push (ax
)));
1382 /* Save MDUC registers inside interrupt routine. */
1383 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1385 for (unsigned i
= 0; i
< ARRAY_SIZE (mduc_regs
); i
++)
1387 mduc_reg_type
*reg
= mduc_regs
+ i
;
1388 rtx mem_mduc
= gen_rtx_MEM (reg
->mode
, GEN_INT (reg
->address
));
1390 MEM_VOLATILE_P (mem_mduc
) = 1;
1391 if (reg
->mode
== QImode
)
1392 emit_insn (gen_movqi (gen_rtx_REG (QImode
, A_REG
), mem_mduc
));
1394 emit_insn (gen_movhi (gen_rtx_REG (HImode
, AX_REG
), mem_mduc
));
1396 emit_insn (gen_push (gen_rtx_REG (HImode
, AX_REG
)));
1400 if (frame_pointer_needed
)
1402 F (emit_move_insn (ax
, sp
));
1403 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
), ax
));
1406 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1409 /* If we need to subtract more than 254*3 then it is faster and
1410 smaller to move SP into AX and perform the subtraction there. */
1415 emit_move_insn (ax
, sp
);
1416 emit_insn (gen_subhi3 (ax
, ax
, GEN_INT (fs
)));
1417 insn
= F (emit_move_insn (sp
, ax
));
1418 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
1419 gen_rtx_SET (sp
, gen_rtx_PLUS (HImode
, sp
,
1426 int fs_byte
= (fs
> 254) ? 254 : fs
;
1428 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1435 /* Expand the function epilogue (from the epilogue pattern). */
1437 rl78_expand_epilogue (void)
1440 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1441 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1444 if (rl78_is_naked_func ())
1447 if (frame_pointer_needed
)
1449 emit_move_insn (ax
, gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1450 emit_move_insn (sp
, ax
);
1454 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1457 emit_move_insn (ax
, sp
);
1458 emit_insn (gen_addhi3 (ax
, ax
, GEN_INT (fs
)));
1459 emit_move_insn (sp
, ax
);
1465 int fs_byte
= (fs
> 254) ? 254 : fs
;
1467 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1473 /* Restore MDUC registers from interrupt routine. */
1474 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1476 for (int i
= ARRAY_SIZE (mduc_regs
) - 1; i
>= 0; i
--)
1478 mduc_reg_type
*reg
= mduc_regs
+ i
;
1479 rtx mem_mduc
= gen_rtx_MEM (reg
->mode
, GEN_INT (reg
->address
));
1481 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1482 MEM_VOLATILE_P (mem_mduc
) = 1;
1483 if (reg
->mode
== QImode
)
1484 emit_insn (gen_movqi (mem_mduc
, gen_rtx_REG (QImode
, A_REG
)));
1486 emit_insn (gen_movhi (mem_mduc
, gen_rtx_REG (HImode
, AX_REG
)));
1490 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1492 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1493 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode
, A_REG
)));
1496 for (i
= 15; i
>= 0; i
--)
1497 if (cfun
->machine
->need_to_push
[i
])
1499 rtx dest
= gen_rtx_REG (HImode
, i
* 2);
1504 emit_insn (gen_pop (dest
));
1507 emit_insn (gen_pop (ax
));
1508 emit_move_insn (dest
, ax
);
1509 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1510 emit_insn (gen_use (dest
));
1515 int need_bank
= i
/ 4;
1517 if (need_bank
!= rb
)
1519 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1522 emit_insn (gen_pop (dest
));
1527 emit_insn (gen_sel_rb (GEN_INT (0)));
1529 if (cfun
->machine
->trampolines_used
)
1530 emit_insn (gen_trampoline_uninit ());
1532 if (is_brk_interrupt_func (cfun
->decl
))
1533 emit_jump_insn (gen_brk_interrupt_return ());
1534 else if (is_interrupt_func (cfun
->decl
))
1535 emit_jump_insn (gen_interrupt_return ());
1537 emit_jump_insn (gen_rl78_return ());
1540 /* Likewise, for exception handlers. */
1542 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1544 /* FIXME - replace this with an indirect jump with stack adjust. */
1545 emit_jump_insn (gen_rl78_return ());
1548 #undef TARGET_ASM_FUNCTION_PROLOGUE
1549 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1551 /* We don't use this to actually emit the function prologue. We use
1552 this to insert a comment in the asm file describing the
1555 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1559 if (cfun
->machine
->framesize
== 0)
1561 fprintf (file
, "\t; start of function\n");
1563 if (cfun
->machine
->framesize_regs
)
1565 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1566 for (i
= 0; i
< 16; i
++)
1567 if (cfun
->machine
->need_to_push
[i
])
1568 fprintf (file
, " %s", word_regnames
[i
*2]);
1569 fprintf (file
, "\n");
1572 if (frame_pointer_needed
)
1573 fprintf (file
, "\t; $fp points here (r22)\n");
1575 if (cfun
->machine
->framesize_locals
)
1576 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1577 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1579 if (cfun
->machine
->framesize_outgoing
)
1580 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1581 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1583 if (cfun
->machine
->uses_es
)
1584 fprintf (file
, "\t; uses ES register\n");
1586 if (MUST_SAVE_MDUC_REGISTERS
)
1587 fprintf (file
, "\t; preserves MDUC registers\n");
1590 /* Return an RTL describing where a function return value of type RET_TYPE
1593 #undef TARGET_FUNCTION_VALUE
1594 #define TARGET_FUNCTION_VALUE rl78_function_value
1597 rl78_function_value (const_tree ret_type
,
1598 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1599 bool outgoing ATTRIBUTE_UNUSED
)
1601 machine_mode mode
= TYPE_MODE (ret_type
);
1603 return gen_rtx_REG (mode
, 8);
1606 #undef TARGET_PROMOTE_FUNCTION_MODE
1607 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1610 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1612 int *punsignedp ATTRIBUTE_UNUSED
,
1613 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1618 /* Return an RTL expression describing the register holding a function
1619 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1620 be passed on the stack. CUM describes the previous parameters to the
1621 function and NAMED is false if the parameter is part of a variable
1622 parameter list, or the last named parameter before the start of a
1623 variable parameter list. */
1625 #undef TARGET_FUNCTION_ARG
1626 #define TARGET_FUNCTION_ARG rl78_function_arg
1629 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1630 machine_mode mode ATTRIBUTE_UNUSED
,
1631 const_tree type ATTRIBUTE_UNUSED
,
1632 bool named ATTRIBUTE_UNUSED
)
1637 #undef TARGET_FUNCTION_ARG_ADVANCE
1638 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1641 rl78_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
, const_tree type
,
1642 bool named ATTRIBUTE_UNUSED
)
1645 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1647 rounded_size
= ((mode
== BLKmode
)
1648 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1649 if (rounded_size
& 1)
1651 (*cum
) += rounded_size
;
1654 #undef TARGET_FUNCTION_ARG_BOUNDARY
1655 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1658 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED
,
1659 const_tree type ATTRIBUTE_UNUSED
)
1664 /* Supported modifier letters:
1666 A - address of a MEM
1667 S - SADDR form of a real register
1668 v - real register corresponding to a virtual register
1669 m - minus - negative of CONST_INT value.
1670 C - inverse of a conditional (NE vs EQ for example)
1671 C - complement of an integer
1672 z - collapsed conditional
1673 s - shift count mod 8
1674 S - shift count mod 16
1675 r - reverse shift count (8-(count mod 8))
1678 h - bottom HI of an SI
1680 q - bottom QI of an HI
1682 e - third QI of an SI (i.e. where the ES register gets values from)
1683 E - fourth QI of an SI (i.e. MSB)
1685 p - Add +0 to a zero-indexed HL based address.
1688 /* Implements the bulk of rl78_print_operand, below. We do it this
1689 way because we need to test for a constant at the top level and
1690 insert the '#', but not test for it anywhere else as we recurse
1691 down into the operand. */
1693 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1697 switch (GET_CODE (op
))
1701 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1704 if (rl78_far_p (op
))
1706 fprintf (file
, "es:");
1707 if (GET_CODE (XEXP (op
, 0)) == UNSPEC
)
1708 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1712 op
= adjust_address (op
, HImode
, 2);
1717 op
= adjust_address (op
, HImode
, 0);
1722 op
= adjust_address (op
, QImode
, 1);
1727 op
= adjust_address (op
, QImode
, 0);
1732 op
= adjust_address (op
, QImode
, 2);
1737 op
= adjust_address (op
, QImode
, 3);
1740 if (CONSTANT_P (XEXP (op
, 0)))
1742 if (!rl78_saddr_p (op
))
1743 fprintf (file
, "!");
1744 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1746 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1747 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1749 if (!rl78_saddr_p (op
))
1750 fprintf (file
, "!");
1751 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1753 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1754 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1755 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1757 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1758 fprintf (file
, "[");
1759 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1760 if (letter
== 'p' && GET_CODE (XEXP (op
, 0)) == REG
)
1761 fprintf (file
, "+0");
1762 fprintf (file
, "]");
1767 fprintf (file
, "[");
1768 rl78_print_operand_1 (file
, op
, letter
);
1769 if (letter
== 'p' && REG_P (op
) && REGNO (op
) == 6)
1770 fprintf (file
, "+0");
1771 fprintf (file
, "]");
1778 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1779 else if (letter
== 'H')
1780 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1781 else if (letter
== 'q')
1782 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1783 else if (letter
== 'e')
1784 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1785 else if (letter
== 'E')
1786 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1787 else if (letter
== 'S')
1788 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1789 else if (GET_MODE (op
) == HImode
1790 && ! (REGNO (op
) & ~0xfe))
1793 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1795 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1798 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1803 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1804 else if (letter
== 'H')
1805 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1806 else if (letter
== 'q')
1807 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1808 else if (letter
== 'h')
1809 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1810 else if (letter
== 'e')
1811 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1812 else if (letter
== 'B')
1814 int ival
= INTVAL (op
);
1817 if (exact_log2 (ival
) >= 0)
1818 fprintf (file
, "%d", exact_log2 (ival
));
1820 fprintf (file
, "%d", exact_log2 (~ival
& 0xff));
1822 else if (letter
== 'E')
1823 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1824 else if (letter
== 'm')
1825 fprintf (file
, "%ld", - INTVAL (op
));
1826 else if (letter
== 's')
1827 fprintf (file
, "%ld", INTVAL (op
) % 8);
1828 else if (letter
== 'S')
1829 fprintf (file
, "%ld", INTVAL (op
) % 16);
1830 else if (letter
== 'r')
1831 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1832 else if (letter
== 'C')
1833 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1835 fprintf (file
, "%ld", INTVAL (op
));
1839 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1844 int bits
= INTVAL (XEXP (op
, 1));
1845 int ofs
= INTVAL (XEXP (op
, 2));
1846 if (bits
== 16 && ofs
== 0)
1847 fprintf (file
, "%%lo16(");
1848 else if (bits
== 16 && ofs
== 16)
1849 fprintf (file
, "%%hi16(");
1850 else if (bits
== 8 && ofs
== 16)
1851 fprintf (file
, "%%hi8(");
1854 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1855 fprintf (file
, ")");
1860 if (GET_CODE (XEXP (op
, 0)) == REG
)
1861 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1863 print_rtl (file
, op
);
1870 fprintf (file
, "%%hi16(");
1876 fprintf (file
, "%%lo16(");
1882 fprintf (file
, "%%hi8(");
1886 if (letter
== 'q' || letter
== 'Q')
1887 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1889 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1891 if (GET_CODE (XEXP (op
, 1)) == SYMBOL_REF
1892 && SYMBOL_REF_DECL (XEXP (op
, 1))
1893 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 1))) == FUNCTION_DECL
)
1895 fprintf (file
, "%%code(");
1896 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 1), 0)));
1897 fprintf (file
, "+");
1898 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1899 fprintf (file
, ")");
1903 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1904 fprintf (file
, "+");
1905 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1910 if (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1911 && SYMBOL_REF_DECL (XEXP (op
, 0))
1912 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 0))) == FUNCTION_DECL
)
1914 fprintf (file
, "%%code(");
1915 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 0), 0)));
1916 fprintf (file
, "+");
1917 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1918 fprintf (file
, ")");
1922 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1923 fprintf (file
, "+");
1924 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1928 fprintf (file
, ")");
1932 if (GET_MODE (op
) == HImode
1933 && SUBREG_BYTE (op
) == 0)
1935 fprintf (file
, "%%lo16(");
1936 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1937 fprintf (file
, ")");
1939 else if (GET_MODE (op
) == HImode
1940 && SUBREG_BYTE (op
) == 2)
1942 fprintf (file
, "%%hi16(");
1943 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1944 fprintf (file
, ")");
1948 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1956 fprintf (file
, "%%hi16(");
1962 fprintf (file
, "%%lo16(");
1968 fprintf (file
, "%%hi8(");
1972 if (letter
== 'q' || letter
== 'Q')
1973 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1975 if (SYMBOL_REF_DECL (op
) && TREE_CODE (SYMBOL_REF_DECL (op
)) == FUNCTION_DECL
)
1977 fprintf (file
, "%%code(");
1978 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
1979 fprintf (file
, ")");
1982 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
1984 fprintf (file
, ")");
1989 output_asm_label (op
);
1994 fprintf (file
, "#comparison eliminated");
1996 fprintf (file
, letter
== 'C' ? "nc" : "c");
2000 fprintf (file
, "br");
2002 fprintf (file
, letter
== 'C' ? "h" : "nh");
2006 fprintf (file
, "br");
2008 fprintf (file
, letter
== 'C' ? "c" : "nc");
2012 fprintf (file
, "#comparison eliminated");
2014 fprintf (file
, letter
== 'C' ? "nh" : "h");
2018 fprintf (file
, "br");
2020 fprintf (file
, letter
== 'C' ? "nz" : "z");
2024 fprintf (file
, "#comparison eliminated");
2026 fprintf (file
, letter
== 'C' ? "z" : "nz");
2029 /* Note: these assume appropriate adjustments were made so that
2030 unsigned comparisons, which is all this chip has, will
2034 fprintf (file
, "#comparison eliminated");
2036 fprintf (file
, letter
== 'C' ? "nc" : "c");
2040 fprintf (file
, "br");
2042 fprintf (file
, letter
== 'C' ? "h" : "nh");
2046 fprintf (file
, "br");
2048 fprintf (file
, letter
== 'C' ? "c" : "nc");
2052 fprintf (file
, "#comparison eliminated");
2054 fprintf (file
, letter
== 'C' ? "nh" : "h");
2058 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
2063 #undef TARGET_PRINT_OPERAND
2064 #define TARGET_PRINT_OPERAND rl78_print_operand
2067 rl78_print_operand (FILE * file
, rtx op
, int letter
)
2069 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
2070 fprintf (file
, "#");
2071 rl78_print_operand_1 (file
, op
, letter
);
2074 #undef TARGET_TRAMPOLINE_INIT
2075 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
2077 /* Note that the RL78's addressing makes it very difficult to do
2078 trampolines on the stack. So, libgcc has a small pool of
2079 trampolines from which one is allocated to this task. */
2081 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2083 rtx mov_addr
, thunk_addr
;
2084 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
2086 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
2087 thunk_addr
= gen_reg_rtx (HImode
);
2089 function
= force_reg (HImode
, function
);
2090 static_chain
= force_reg (HImode
, static_chain
);
2092 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
2093 emit_move_insn (mov_addr
, thunk_addr
);
2095 cfun
->machine
->trampolines_used
= 1;
2098 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2099 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2102 rl78_trampoline_adjust_address (rtx m_tramp
)
2104 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
2108 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2109 the "normal" compares, specifically, it only has unsigned compares,
2110 so we must synthesize the missing ones. */
2112 rl78_expand_compare (rtx
*operands
)
2114 if (GET_CODE (operands
[2]) == MEM
)
2115 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
2120 /* Define this to 1 if you are debugging the peephole optimizers. */
2121 #define DEBUG_PEEP 0
2123 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2124 The default "word" size is a byte so we can effectively use all the
2125 registers, but we want to do 16-bit moves whenever possible. This
2126 function determines when such a move is an option. */
2128 rl78_peep_movhi_p (rtx
*operands
)
2133 /* (set (op0) (op1))
2134 (set (op2) (op3)) */
2136 if (! rl78_virt_insns_ok ())
2140 fprintf (stderr
, "\033[33m");
2141 debug_rtx (operands
[0]);
2142 debug_rtx (operands
[1]);
2143 debug_rtx (operands
[2]);
2144 debug_rtx (operands
[3]);
2145 fprintf (stderr
, "\033[0m");
2148 /* You can move a constant to memory as QImode, but not HImode. */
2149 if (GET_CODE (operands
[0]) == MEM
2150 && GET_CODE (operands
[1]) != REG
)
2153 fprintf (stderr
, "no peep: move constant to memory\n");
2158 if (rtx_equal_p (operands
[0], operands
[3]))
2161 fprintf (stderr
, "no peep: overlapping\n");
2166 for (i
= 0; i
< 2; i
++)
2168 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
2171 fprintf (stderr
, "no peep: different codes\n");
2175 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
2178 fprintf (stderr
, "no peep: different modes\n");
2183 switch (GET_CODE (operands
[i
]))
2187 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
2188 || GET_MODE (operands
[i
]) != QImode
)
2191 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
2192 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
2197 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
2200 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
2210 if (GET_MODE (operands
[i
]) != QImode
)
2212 if (MEM_ALIGN (operands
[i
]) < 16)
2214 a
= XEXP (operands
[i
], 0);
2215 if (GET_CODE (a
) == CONST
)
2217 if (GET_CODE (a
) == PLUS
)
2219 if (GET_CODE (a
) == CONST_INT
2223 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
2224 debug_rtx (operands
[i
]);
2228 m
= adjust_address (operands
[i
], QImode
, 1);
2229 if (! rtx_equal_p (m
, operands
[i
+2]))
2232 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
2234 debug_rtx (operands
[i
+2]);
2242 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
2248 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
2253 /* Likewise, when a peephole is activated, this function helps compute
2254 the new operands. */
2256 rl78_setup_peep_movhi (rtx
*operands
)
2260 for (i
= 0; i
< 2; i
++)
2262 switch (GET_CODE (operands
[i
]))
2265 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
2269 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char) INTVAL (operands
[i
+2])) * 256);
2273 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
2283 How Devirtualization works in the RL78 GCC port
2287 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2288 bytes of register space, in four banks, memory-mapped. One bank is
2289 the "selected" bank and holds the registers used for primary
2290 operations. Since the registers are memory mapped, often you can
2291 still refer to the unselected banks via memory accesses.
2295 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2296 and refers to the other banks via their memory addresses, although
2297 they're treated as regular registers internally. These "virtual"
2298 registers are R8 through R23 (bank3 is reserved for asm-based
2299 interrupt handlers).
2301 There are four machine description files:
2303 rl78.md - common register-independent patterns and definitions
2304 rl78-expand.md - expanders
2305 rl78-virt.md - patterns that match BEFORE devirtualization
2306 rl78-real.md - patterns that match AFTER devirtualization
2308 At least through register allocation and reload, gcc is told that it
2309 can do pretty much anything - but may only use the virtual registers.
2310 GCC cannot properly create the varying addressing modes that the RL78
2311 supports in an efficient way.
2313 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2314 uses the "valloc" attribute in rl78-virt.md for determining the rules
2315 by which it will replace virtual registers with real registers (or
2316 not) and how to make up addressing modes. For example, insns tagged
2317 with "ro1" have a single read-only parameter, which may need to be
2318 moved from memory/constant/vreg to a suitable real register. As part
2319 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2320 patterns and enabling the rl78-real.md patterns. The new patterns'
2321 constraints are used to determine the real registers used. NOTE:
2322 patterns in rl78-virt.md essentially ignore the constrains and rely on
2323 predicates, where the rl78-real.md ones essentially ignore the
2324 predicates and rely on the constraints.
2326 The devirtualization pass is scheduled via the pass manager (despite
2327 being called "rl78_reorg") so it can be scheduled prior to var-track
2328 (the idea is to let gdb know about the new registers). Ideally, it
2329 would be scheduled right after pro/epilogue generation, so the
2330 post-reload optimizers could operate on the real registers, but when I
2331 tried that there were some issues building the target libraries.
2333 During devirtualization, a simple register move optimizer is run. It
2334 would be better to run a full CSE/propogation pass on it though, but
2335 that has not yet been attempted.
2338 #define DEBUG_ALLOC 0
2340 #define OP(x) (*recog_data.operand_loc[x])
2342 /* This array is used to hold knowledge about the contents of the
2343 real registers (A ... H), the memory-based registers (r8 ... r31)
2344 and the first NUM_STACK_LOCS words on the stack. We use this to
2345 avoid generating redundant move instructions.
2347 A value in the range 0 .. 31 indicates register A .. r31.
2348 A value in the range 32 .. 63 indicates stack slot (value - 32).
2349 A value of NOT_KNOWN indicates that the contents of that location
2352 #define NUM_STACK_LOCS 32
2353 #define NOT_KNOWN 127
2355 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
2357 static unsigned char saved_update_index
= NOT_KNOWN
;
2358 static unsigned char saved_update_value
;
2359 static machine_mode saved_update_mode
;
2363 clear_content_memory (void)
2365 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
2367 fprintf (dump_file
, " clear content memory\n");
2368 saved_update_index
= NOT_KNOWN
;
2371 /* Convert LOC into an index into the content_memory array.
2372 If LOC cannot be converted, return NOT_KNOWN. */
2374 static unsigned char
2375 get_content_index (rtx loc
)
2379 if (loc
== NULL_RTX
)
2384 if (REGNO (loc
) < 32)
2389 mode
= GET_MODE (loc
);
2391 if (! rl78_stack_based_mem (loc
, mode
))
2394 loc
= XEXP (loc
, 0);
2397 /* loc = MEM (SP) */
2400 /* loc = MEM (PLUS (SP, INT)). */
2401 loc
= XEXP (loc
, 1);
2403 if (INTVAL (loc
) < NUM_STACK_LOCS
)
2404 return 32 + INTVAL (loc
);
2409 /* Return a string describing content INDEX in mode MODE.
2410 WARNING: Can return a pointer to a static buffer. */
2412 get_content_name (unsigned char index
, machine_mode mode
)
2414 static char buffer
[128];
2416 if (index
== NOT_KNOWN
)
2420 sprintf (buffer
, "stack slot %d", index
- 32);
2421 else if (mode
== HImode
)
2422 sprintf (buffer
, "%s%s",
2423 reg_names
[index
+ 1], reg_names
[index
]);
2425 return reg_names
[index
];
2433 display_content_memory (FILE * file
)
2437 fprintf (file
, " Known memory contents:\n");
2439 for (i
= 0; i
< sizeof content_memory
; i
++)
2440 if (content_memory
[i
] != NOT_KNOWN
)
2442 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
2443 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2449 update_content (unsigned char index
, unsigned char val
, machine_mode mode
)
2453 gcc_assert (index
< sizeof content_memory
);
2455 content_memory
[index
] = val
;
2456 if (val
!= NOT_KNOWN
)
2457 content_memory
[val
] = index
;
2459 /* Make the entry in dump_file *before* VAL is increased below. */
2462 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2463 if (val
== NOT_KNOWN
)
2464 fprintf (dump_file
, "Unknown\n");
2466 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2471 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2473 content_memory
[index
+ 1] = val
;
2474 if (val
!= NOT_KNOWN
)
2476 content_memory
[val
] = index
+ 1;
2481 /* Any other places that had INDEX recorded as their contents are now invalid. */
2482 for (i
= 0; i
< sizeof content_memory
; i
++)
2485 || (val
!= NOT_KNOWN
&& i
== val
))
2492 if (content_memory
[i
] == index
2493 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2495 content_memory
[i
] = NOT_KNOWN
;
2498 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2501 content_memory
[++ i
] = NOT_KNOWN
;
2506 /* Record that LOC contains VALUE.
2507 For HImode locations record that LOC+1 contains VALUE+1.
2508 If LOC is not a register or stack slot, do nothing.
2509 If VALUE is not a register or stack slot, clear the recorded content. */
2512 record_content (rtx loc
, rtx value
)
2515 unsigned char index
;
2518 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2521 val
= get_content_index (value
);
2523 mode
= GET_MODE (loc
);
2530 /* This should not happen when optimizing. */
2532 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2533 get_content_name (val
, mode
));
2540 update_content (index
, val
, mode
);
2543 /* Returns TRUE if LOC already contains a copy of VALUE. */
2546 already_contains (rtx loc
, rtx value
)
2548 unsigned char index
;
2551 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2554 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2557 if (content_memory
[index
] != val
)
2560 if (GET_MODE (loc
) == HImode
)
2561 return content_memory
[index
+ 1] == val
+ 1;
2567 rl78_es_addr (rtx addr
)
2569 if (GET_CODE (addr
) == MEM
)
2570 addr
= XEXP (addr
, 0);
2571 if (GET_CODE (addr
) != UNSPEC
)
2573 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2579 rl78_es_base (rtx addr
)
2581 if (GET_CODE (addr
) == MEM
)
2582 addr
= XEXP (addr
, 0);
2583 addr
= XVECEXP (addr
, 0, 1);
2584 if (GET_CODE (addr
) == CONST
2585 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2586 addr
= XEXP (XEXP (addr
, 0), 0);
2587 /* Mode doesn't matter here. */
2588 return gen_rtx_MEM (HImode
, addr
);
2591 /* Rescans an insn to see if it's recognized again. This is done
2592 carefully to ensure that all the constraint information is accurate
2593 for the newly matched insn. */
2595 insn_ok_now (rtx_insn
* insn
)
2597 rtx pattern
= PATTERN (insn
);
2600 INSN_CODE (insn
) = -1;
2602 if (recog (pattern
, insn
, 0) > -1)
2604 extract_insn (insn
);
2605 if (constrain_operands (1, get_preferred_alternatives (insn
)))
2608 fprintf (stderr
, "\033[32m");
2610 fprintf (stderr
, "\033[0m");
2612 if (SET_P (pattern
))
2613 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2615 /* We need to detect far addresses that haven't been
2616 converted to es/lo16 format. */
2617 for (i
=0; i
<recog_data
.n_operands
; i
++)
2618 if (GET_CODE (OP (i
)) == MEM
2619 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2620 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2628 /* We need to re-recog the insn with virtual registers to get
2630 cfun
->machine
->virt_insns_ok
= 1;
2631 if (recog (pattern
, insn
, 0) > -1)
2633 extract_insn (insn
);
2634 if (constrain_operands (0, get_preferred_alternatives (insn
)))
2636 cfun
->machine
->virt_insns_ok
= 0;
2642 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2649 fprintf (stderr
, "\033[31m");
2651 fprintf (stderr
, "\033[0m");
2657 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2658 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2659 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2660 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2661 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2663 #define FAILED gcc_unreachable ()
2664 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2665 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2668 /* Registers into which we move the contents of virtual registers. */
2669 #define X gen_rtx_REG (QImode, X_REG)
2670 #define A gen_rtx_REG (QImode, A_REG)
2671 #define C gen_rtx_REG (QImode, C_REG)
2672 #define B gen_rtx_REG (QImode, B_REG)
2673 #define E gen_rtx_REG (QImode, E_REG)
2674 #define D gen_rtx_REG (QImode, D_REG)
2675 #define L gen_rtx_REG (QImode, L_REG)
2676 #define H gen_rtx_REG (QImode, H_REG)
2678 #define AX gen_rtx_REG (HImode, AX_REG)
2679 #define BC gen_rtx_REG (HImode, BC_REG)
2680 #define DE gen_rtx_REG (HImode, DE_REG)
2681 #define HL gen_rtx_REG (HImode, HL_REG)
2683 /* Returns TRUE if R is a virtual register. */
2685 is_virtual_register (rtx r
)
2687 return (GET_CODE (r
) == REG
2692 /* In all these alloc routines, we expect the following: the insn
2693 pattern is unshared, the insn was previously recognized and failed
2694 due to predicates or constraints, and the operand data is in
2697 static int virt_insn_was_frame
;
2699 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2702 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2705 fprintf (stderr
, "\033[36m%d: ", line
);
2707 fprintf (stderr
, "\033[0m");
2709 /*SCHED_GROUP_P (r) = 1;*/
2710 if (virt_insn_was_frame
)
2711 RTX_FRAME_RELATED_P (r
) = 1;
2715 #define EM(x) EM2 (__LINE__, x)
2717 /* Return a suitable RTX for the low half of a __far address. */
2719 rl78_lo16 (rtx addr
)
2723 if (GET_CODE (addr
) == SYMBOL_REF
2724 || GET_CODE (addr
) == CONST
)
2726 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2727 r
= gen_rtx_CONST (HImode
, r
);
2730 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2732 r
= gen_es_addr (r
);
2733 cfun
->machine
->uses_es
= true;
2738 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2742 if (GET_CODE (addr
) == SYMBOL_REF
2743 || GET_CODE (addr
) == CONST
)
2745 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2746 r
= gen_rtx_CONST (QImode
, r
);
2749 return rl78_subreg (QImode
, addr
, SImode
, 2);
2753 add_postponed_content_update (rtx to
, rtx value
)
2755 unsigned char index
;
2757 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2760 gcc_assert (saved_update_index
== NOT_KNOWN
);
2761 saved_update_index
= index
;
2762 saved_update_value
= get_content_index (value
);
2763 saved_update_mode
= GET_MODE (to
);
2767 process_postponed_content_update (void)
2769 if (saved_update_index
!= NOT_KNOWN
)
2771 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2772 saved_update_index
= NOT_KNOWN
;
2776 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2777 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2778 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2779 BEFORE is true, FROM otherwise. */
2781 gen_and_emit_move (rtx to
, rtx from
, rtx_insn
*where
, bool before
)
2783 machine_mode mode
= GET_MODE (to
);
2785 if (optimize
&& before
&& already_contains (to
, from
))
2788 display_content_memory (stderr
);
2792 fprintf (dump_file
, " Omit move of %s into ",
2793 get_content_name (get_content_index (from
), mode
));
2794 fprintf (dump_file
, "%s as it already contains this value\n",
2795 get_content_name (get_content_index (to
), mode
));
2800 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2804 if (where
== NULL_RTX
)
2807 emit_insn_before (move
, where
);
2810 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2812 /* If necessary move REG_EH_REGION notes forward.
2813 cf. compiling gcc.dg/pr44545.c. */
2814 if (note
!= NULL_RTX
)
2816 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2817 remove_note (where
, note
);
2820 emit_insn_after (move
, where
);
2824 record_content (to
, from
);
2826 add_postponed_content_update (to
, from
);
2829 return before
? to
: from
;
2832 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2833 copy it into NEWBASE and return the updated MEM. Otherwise just
2834 return M. Any needed insns are emitted before BEFORE. */
2836 transcode_memory_rtx (rtx m
, rtx newbase
, rtx_insn
*before
)
2838 rtx base
, index
, addendr
;
2845 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2848 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2852 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2853 emit_insn_before (EM (gen_movqi_to_es (A
)), before
);
2856 record_content (A
, NULL_RTX
);
2858 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2859 MEM_COPY_ATTRIBUTES (new_m
, m
);
2864 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2865 gcc_assert (index
== NULL_RTX
);
2867 if (base
== NULL_RTX
)
2870 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2871 addend
= INTVAL (addendr
);
2873 gcc_assert (REG_P (base
));
2874 gcc_assert (REG_P (newbase
));
2876 int limit
= 256 - GET_MODE_SIZE (GET_MODE (m
));
2878 if (REGNO (base
) == SP_REG
)
2880 if (addend
>= 0 && addend
<= limit
)
2884 /* BASE should be a virtual register. We copy it to NEWBASE. If
2885 the addend is out of range for DE/HL, we use AX to compute the full
2889 || (addend
> limit
&& REGNO (newbase
) != BC_REG
)
2891 && (GET_CODE (addendr
) != CONST_INT
)
2892 && ((REGNO (newbase
) != BC_REG
))
2898 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2899 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2900 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2901 record_content (AX
, NULL_RTX
);
2902 record_content (newbase
, NULL_RTX
);
2910 base
= gen_and_emit_move (newbase
, base
, before
, true);
2915 record_content (base
, NULL_RTX
);
2916 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2920 record_content (base
, NULL_RTX
);
2921 base
= gen_rtx_PLUS (HImode
, base
, addendr
);
2926 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2927 cfun
->machine
->uses_es
= true;
2930 m
= change_address (m
, GET_MODE (m
), base
);
2934 /* Copy SRC to accumulator (A or AX), placing any generated insns
2935 before BEFORE. Returns accumulator RTX. */
2937 move_to_acc (int opno
, rtx_insn
*before
)
2939 rtx src
= OP (opno
);
2940 machine_mode mode
= GET_MODE (src
);
2942 if (REG_P (src
) && REGNO (src
) < 2)
2945 if (mode
== VOIDmode
)
2946 mode
= recog_data
.operand_mode
[opno
];
2948 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2952 force_into_acc (rtx src
, rtx_insn
*before
)
2954 machine_mode mode
= GET_MODE (src
);
2957 if (REG_P (src
) && REGNO (src
) < 2)
2960 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2964 emit_insn_before (move
, before
);
2965 record_content (AX
, NULL_RTX
);
2968 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2969 after AFTER. Returns accumulator RTX. */
2971 move_from_acc (unsigned int opno
, rtx_insn
*after
)
2973 rtx dest
= OP (opno
);
2974 machine_mode mode
= GET_MODE (dest
);
2976 if (REG_P (dest
) && REGNO (dest
) < 2)
2979 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2982 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2983 before BEFORE. Returns reg RTX. */
2985 move_acc_to_reg (rtx acc
, int regno
, rtx_insn
*before
)
2987 machine_mode mode
= GET_MODE (acc
);
2990 reg
= gen_rtx_REG (mode
, regno
);
2992 return gen_and_emit_move (reg
, acc
, before
, true);
2995 /* Copy SRC to X, placing any generated insns before BEFORE.
2998 move_to_x (int opno
, rtx_insn
*before
)
3000 rtx src
= OP (opno
);
3001 machine_mode mode
= GET_MODE (src
);
3004 if (mode
== VOIDmode
)
3005 mode
= recog_data
.operand_mode
[opno
];
3006 reg
= (mode
== QImode
) ? X
: AX
;
3008 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3010 OP (opno
) = move_to_acc (opno
, before
);
3011 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
3015 return gen_and_emit_move (reg
, src
, before
, true);
3018 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
3019 Returns H/HL RTX. */
3021 move_to_hl (int opno
, rtx_insn
*before
)
3023 rtx src
= OP (opno
);
3024 machine_mode mode
= GET_MODE (src
);
3027 if (mode
== VOIDmode
)
3028 mode
= recog_data
.operand_mode
[opno
];
3029 reg
= (mode
== QImode
) ? L
: HL
;
3031 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3033 OP (opno
) = move_to_acc (opno
, before
);
3034 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
3038 return gen_and_emit_move (reg
, src
, before
, true);
3041 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
3042 Returns E/DE RTX. */
3044 move_to_de (int opno
, rtx_insn
*before
)
3046 rtx src
= OP (opno
);
3047 machine_mode mode
= GET_MODE (src
);
3050 if (mode
== VOIDmode
)
3051 mode
= recog_data
.operand_mode
[opno
];
3053 reg
= (mode
== QImode
) ? E
: DE
;
3055 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3057 OP (opno
) = move_to_acc (opno
, before
);
3058 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
3062 gen_and_emit_move (reg
, src
, before
, true);
3068 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
3070 rl78_alloc_physical_registers_op1 (rtx_insn
* insn
)
3072 /* op[0] = func op[1] */
3074 /* We first try using A as the destination, then copying it
3076 if (rtx_equal_p (OP (0), OP (1)))
3079 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3083 /* If necessary, load the operands into BC and HL.
3084 Check to see if we already have OP (0) in HL
3085 and if so, swap the order.
3087 It is tempting to perform this optimization when OP(0) does
3088 not hold a MEM, but this leads to bigger code in general.
3089 The problem is that if OP(1) holds a MEM then swapping it
3090 into BC means a BC-relative load is used and these are 3
3091 bytes long vs 1 byte for an HL load. */
3093 && already_contains (HL
, XEXP (OP (0), 0)))
3095 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
3096 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
3100 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3101 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3107 OP (0) = move_from_acc (0, insn
);
3111 /* Try copying the src to acc first, then. This is for, for
3112 example, ZERO_EXTEND or NOT. */
3113 OP (1) = move_to_acc (1, insn
);
3118 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3119 Assumes that the current insn has already been recognised and hence the
3120 constraint data has been filled in. */
3122 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
3124 const char * p
= recog_data
.constraints
[opnum
];
3126 /* No constraints means anything is accepted. */
3127 if (p
== NULL
|| *p
== 0 || *p
== ',')
3136 len
= CONSTRAINT_LEN (c
, p
);
3137 gcc_assert (len
> 0);
3145 if (lookup_constraint (p
) == constraint
)
3153 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3155 rl78_alloc_physical_registers_op2 (rtx_insn
* insn
)
3163 if (rtx_equal_p (OP (0), OP (1)))
3168 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3169 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3174 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3175 OP (2) = transcode_memory_rtx (OP (2), DE
, insn
);
3178 else if (rtx_equal_p (OP (0), OP (2)))
3180 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3182 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3186 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3187 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3188 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3193 prev
= prev_nonnote_nondebug_insn (insn
);
3194 if (recog_data
.constraints
[1][0] == '%'
3195 && is_virtual_register (OP (1))
3196 && ! is_virtual_register (OP (2))
3197 && ! CONSTANT_P (OP (2)))
3204 /* Make a note of whether (H)L is being used. It matters
3205 because if OP (2) also needs reloading, then we must take
3206 care not to corrupt HL. */
3207 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
3209 /* If HL is not currently being used and dest == op1 then there are
3210 some possible optimizations available by reloading one of the
3211 operands into HL, before trying to use the accumulator. */
3214 && rtx_equal_p (OP (0), OP (1)))
3216 /* If op0 is a Ws1 type memory address then switching the base
3217 address register to HL might allow us to perform an in-memory
3218 operation. (eg for the INCW instruction).
3220 FIXME: Adding the move into HL is costly if this optimization is not
3221 going to work, so for now, make sure that we know that the new insn will
3222 match the requirements of the addhi3_real pattern. Really we ought to
3223 generate a candidate sequence, test that, and then install it if the
3224 results are good. */
3225 if (satisfies_constraint_Ws1 (OP (0))
3226 && has_constraint (0, CONSTRAINT_Wh1
)
3227 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3229 rtx base
, index
, addend
, newbase
;
3231 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
3232 gcc_assert (index
== NULL_RTX
);
3233 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3235 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3236 if (addend
!= NULL_RTX
)
3238 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
3239 record_content (newbase
, NULL_RTX
);
3240 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
3242 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
3244 /* We do not want to fail here as this means that
3245 we have inserted useless insns into the stream. */
3249 else if (REG_P (OP (0))
3250 && satisfies_constraint_Ws1 (OP (2))
3251 && has_constraint (2, CONSTRAINT_Wh1
))
3253 rtx base
, index
, addend
, newbase
;
3255 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
3256 gcc_assert (index
== NULL_RTX
);
3257 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3259 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3260 if (addend
!= NULL_RTX
)
3262 gen_and_emit_move (HL
, base
, insn
, true);
3264 if (REGNO (OP (0)) != X_REG
)
3266 OP (1) = move_to_acc (1, insn
);
3267 OP (0) = move_from_acc (0, insn
);
3270 record_content (HL
, NULL_RTX
);
3271 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
3273 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
3275 /* We do not want to fail here as this means that
3276 we have inserted useless insns into the stream. */
3282 OP (0) = move_from_acc (0, insn
);
3284 tmp_id
= get_max_insn_count ();
3287 if (rtx_equal_p (OP (1), OP (2)))
3288 OP (2) = OP (1) = move_to_acc (1, insn
);
3290 OP (1) = move_to_acc (1, insn
);
3294 /* If we omitted the move of OP1 into the accumulator (because
3295 it was already there from a previous insn), then force the
3296 generation of the move instruction now. We know that we
3297 are about to emit a move into HL (or DE) via AX, and hence
3298 our optimization to remove the load of OP1 is no longer valid. */
3299 if (tmp_id
== get_max_insn_count ())
3300 force_into_acc (saved_op1
, insn
);
3302 /* We have to copy op2 to HL (or DE), but that involves AX, which
3303 already has a live value. Emit it before those insns. */
3306 first
= next_nonnote_nondebug_insn (prev
);
3308 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3311 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
3316 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3318 rl78_alloc_physical_registers_ro1 (rtx_insn
* insn
)
3320 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3324 OP (0) = move_to_acc (0, insn
);
3329 /* Devirtualize a compare insn. */
3331 rl78_alloc_physical_registers_cmp (rtx_insn
* insn
)
3335 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3338 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3339 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3341 /* HI compares have to have OP (1) in AX, but QI
3342 compares do not, so it is worth checking here. */
3345 /* For an HImode compare, OP (1) must always be in AX.
3346 But if OP (1) is a REG (and not AX), then we can avoid
3347 a reload of OP (1) if we reload OP (2) into AX and invert
3350 && REGNO (OP (1)) != AX_REG
3351 && GET_MODE (OP (1)) == HImode
3354 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
3356 OP (2) = move_to_acc (2, insn
);
3358 switch (GET_CODE (cmp
))
3363 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
3364 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
3365 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
3366 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
3379 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
3380 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
3382 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
3387 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3388 should be handled by the second alternative of the cbranchhi_real pattern. */
3389 if (rtx_equal_p (OP (1), OP (2)))
3391 OP (1) = OP (2) = BC
;
3395 tmp_id
= get_max_insn_count ();
3398 OP (1) = move_to_acc (1, insn
);
3402 /* If we omitted the move of OP1 into the accumulator (because
3403 it was already there from a previous insn), then force the
3404 generation of the move instruction now. We know that we
3405 are about to emit a move into HL via AX, and hence our
3406 optimization to remove the load of OP1 is no longer valid. */
3407 if (tmp_id
== get_max_insn_count ())
3408 force_into_acc (saved_op1
, insn
);
3410 /* We have to copy op2 to HL, but that involves the acc, which
3411 already has a live value. Emit it before those insns. */
3413 first
= next_nonnote_nondebug_insn (prev
);
3415 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3417 OP (2) = move_to_hl (2, first
);
3422 /* Like op2, but AX = A * X. */
3424 rl78_alloc_physical_registers_umul (rtx_insn
* insn
)
3426 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3431 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3432 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3433 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3437 if (recog_data
.constraints
[1][0] == '%'
3438 && is_virtual_register (OP (1))
3439 && !is_virtual_register (OP (2))
3440 && !CONSTANT_P (OP (2)))
3447 OP (0) = move_from_acc (0, insn
);
3449 tmp_id
= get_max_insn_count ();
3452 if (rtx_equal_p (OP (1), OP (2)))
3454 gcc_assert (GET_MODE (OP (2)) == QImode
);
3455 /* The MULU instruction does not support duplicate arguments
3456 but we know that if we copy OP (2) to X it will do so via
3457 A and thus OP (1) will already be loaded into A. */
3458 OP (2) = move_to_x (2, insn
);
3462 OP (1) = move_to_acc (1, insn
);
3466 /* If we omitted the move of OP1 into the accumulator (because
3467 it was already there from a previous insn), then force the
3468 generation of the move instruction now. We know that we
3469 are about to emit a move into HL (or DE) via AX, and hence
3470 our optimization to remove the load of OP1 is no longer valid. */
3471 if (tmp_id
== get_max_insn_count ())
3472 force_into_acc (saved_op1
, insn
);
3474 /* We have to copy op2 to X, but that involves the acc, which
3475 already has a live value. Emit it before those insns. */
3478 first
= next_nonnote_nondebug_insn (prev
);
3480 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3482 OP (2) = move_to_x (2, first
);
3488 rl78_alloc_address_registers_macax (rtx_insn
* insn
)
3491 bool replace_in_op0
= false;
3492 bool replace_in_op1
= false;
3496 /* Two different MEMs are not allowed. */
3498 for (op
= 2; op
>= 0; op
--)
3500 if (MEM_P (OP (op
)))
3502 if (op
== 0 && replace_in_op0
)
3504 if (op
== 1 && replace_in_op1
)
3510 /* If we replace a MEM, make sure that we replace it for all
3511 occurrences of the same MEM in the insn. */
3512 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3513 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3515 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3518 && ((GET_CODE (XEXP (OP (op
), 0)) == REG
3519 && REGNO (XEXP (OP (op
), 0)) == SP_REG
)
3520 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3521 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3523 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3524 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3532 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3535 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3546 rl78_alloc_address_registers_div (rtx_insn
* insn
)
3551 /* Scan all insns and devirtualize them. */
3553 rl78_alloc_physical_registers (void)
3555 /* During most of the compile, gcc is dealing with virtual
3556 registers. At this point, we need to assign physical registers
3557 to the vitual ones, and copy in/out as needed. */
3559 rtx_insn
*insn
, *curr
;
3560 enum attr_valloc valloc_method
;
3562 for (insn
= get_insns (); insn
; insn
= curr
)
3566 curr
= next_nonnote_nondebug_insn (insn
);
3569 && (GET_CODE (PATTERN (insn
)) == SET
3570 || GET_CODE (PATTERN (insn
)) == CALL
)
3571 && INSN_CODE (insn
) == -1)
3573 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3575 i
= recog (PATTERN (insn
), insn
, 0);
3581 INSN_CODE (insn
) = i
;
3585 cfun
->machine
->virt_insns_ok
= 0;
3586 cfun
->machine
->real_insns_ok
= 1;
3588 clear_content_memory ();
3590 for (insn
= get_insns (); insn
; insn
= curr
)
3594 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3599 clear_content_memory ();
3605 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3607 pattern
= PATTERN (insn
);
3608 if (GET_CODE (pattern
) == PARALLEL
)
3609 pattern
= XVECEXP (pattern
, 0, 0);
3610 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3611 clear_content_memory ();
3612 if (GET_CODE (pattern
) != SET
3613 && GET_CODE (pattern
) != CALL
)
3615 if (GET_CODE (pattern
) == SET
3616 && GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3619 valloc_method
= get_attr_valloc (insn
);
3621 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3623 if (valloc_method
== VALLOC_MACAX
)
3625 record_content (AX
, NULL_RTX
);
3626 record_content (BC
, NULL_RTX
);
3627 record_content (DE
, NULL_RTX
);
3629 else if (valloc_method
== VALLOC_DIVHI
)
3631 record_content (AX
, NULL_RTX
);
3632 record_content (BC
, NULL_RTX
);
3634 else if (valloc_method
== VALLOC_DIVSI
)
3636 record_content (AX
, NULL_RTX
);
3637 record_content (BC
, NULL_RTX
);
3638 record_content (DE
, NULL_RTX
);
3639 record_content (HL
, NULL_RTX
);
3642 if (insn_ok_now (insn
))
3645 INSN_CODE (insn
) = -1;
3647 if (RTX_FRAME_RELATED_P (insn
))
3648 virt_insn_was_frame
= 1;
3650 virt_insn_was_frame
= 0;
3652 switch (valloc_method
)
3655 rl78_alloc_physical_registers_op1 (insn
);
3658 rl78_alloc_physical_registers_op2 (insn
);
3661 rl78_alloc_physical_registers_ro1 (insn
);
3664 rl78_alloc_physical_registers_cmp (insn
);
3667 rl78_alloc_physical_registers_umul (insn
);
3668 record_content (AX
, NULL_RTX
);
3671 /* Macro that clobbers AX. */
3672 rl78_alloc_address_registers_macax (insn
);
3673 record_content (AX
, NULL_RTX
);
3674 record_content (BC
, NULL_RTX
);
3675 record_content (DE
, NULL_RTX
);
3678 rl78_alloc_address_registers_div (insn
);
3679 record_content (AX
, NULL_RTX
);
3680 record_content (BC
, NULL_RTX
);
3681 record_content (DE
, NULL_RTX
);
3682 record_content (HL
, NULL_RTX
);
3685 rl78_alloc_address_registers_div (insn
);
3686 record_content (AX
, NULL_RTX
);
3687 record_content (BC
, NULL_RTX
);
3693 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3694 clear_content_memory ();
3696 process_postponed_content_update ();
3700 fprintf (stderr
, "\033[0m");
3704 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3705 This function scans for uses of registers; the last use (i.e. first
3706 encounter when scanning backwards) triggers a REG_DEAD note if the
3707 reg was previously in DEAD[]. */
3709 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3718 code
= GET_CODE (s
);
3722 /* Compare registers by number. */
3727 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3728 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3729 print_rtl_single (dump_file
, s
);
3732 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3733 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3737 /* These codes have no constituent expressions
3748 /* These are kept unique for a given value. */
3755 fmt
= GET_RTX_FORMAT (code
);
3757 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3762 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3763 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3765 else if (fmt
[i
] == 'e')
3766 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3770 /* Like the previous function, but scan for SETs instead. */
3772 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3776 if (GET_CODE (d
) == MEM
)
3777 rl78_note_reg_uses (dead
, XEXP (d
, 0), insn
);
3779 if (GET_CODE (d
) != REG
)
3784 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3786 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3787 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3791 /* This is a rather crude register death pass. Death status is reset
3792 at every jump or call insn. */
3794 rl78_calculate_death_notes (void)
3796 char dead
[FIRST_PSEUDO_REGISTER
];
3801 memset (dead
, 0, sizeof (dead
));
3803 for (insn
= get_last_insn ();
3805 insn
= prev_nonnote_nondebug_insn (insn
))
3809 fprintf (dump_file
, "\n--------------------------------------------------");
3810 fprintf (dump_file
, "\nDead:");
3811 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3813 fprintf (dump_file
, " %s", reg_names
[i
]);
3814 fprintf (dump_file
, "\n");
3815 print_rtl_single (dump_file
, insn
);
3818 switch (GET_CODE (insn
))
3822 if (GET_CODE (p
) == PARALLEL
)
3824 rtx q
= XVECEXP (p
, 0 ,1);
3826 /* This happens with the DIV patterns. */
3827 if (GET_CODE (q
) == SET
)
3831 rl78_note_reg_set (dead
, d
, insn
);
3832 rl78_note_reg_uses (dead
, s
, insn
);
3835 p
= XVECEXP (p
, 0, 0);
3838 switch (GET_CODE (p
))
3843 rl78_note_reg_set (dead
, d
, insn
);
3844 rl78_note_reg_uses (dead
, s
, insn
);
3848 rl78_note_reg_uses (dead
, p
, insn
);
3857 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3859 memset (dead
, 1, sizeof (dead
));
3860 /* We expect a USE just prior to this, which will mark
3861 the actual return registers. The USE will have a
3862 death note, but we aren't going to be modifying it
3868 memset (dead
, 0, sizeof (dead
));
3875 print_rtl_single (dump_file
, insn
);
3879 /* Helper function to reset the origins in RP and the age in AGE for
3882 reset_origins (int *rp
, int *age
)
3885 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3893 set_origin (rtx pat
, rtx_insn
* insn
, int * origins
, int * age
)
3895 rtx src
= SET_SRC (pat
);
3896 rtx dest
= SET_DEST (pat
);
3897 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3900 if (GET_CODE (dest
) == REG
)
3902 int dr
= REGNO (dest
);
3904 if (GET_CODE (src
) == REG
)
3906 int sr
= REGNO (src
);
3908 int best_age
, best_reg
;
3910 /* See if the copy is not needed. */
3911 for (i
= 0; i
< mb
; i
++)
3912 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3918 fprintf (dump_file
, "deleting because dest already has correct value\n");
3923 if (dr
< 8 || sr
>= 8)
3930 /* See if the copy can be made from another
3931 bank 0 register instead, instead of the
3932 virtual src register. */
3933 for (ar
= 0; ar
< 8; ar
+= mb
)
3937 for (i
= 0; i
< mb
; i
++)
3938 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3941 /* The chip has some reg-reg move limitations. */
3942 if (mb
== 1 && dr
> 3)
3947 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3949 best_age
= age
[sr
+ i
];
3957 /* FIXME: copy debug info too. */
3958 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3963 for (i
= 0; i
< mb
; i
++)
3965 origins
[dr
+ i
] = origins
[sr
+ i
];
3966 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3971 /* The destination is computed, its origin is itself. */
3973 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3974 dr
, mb
, mb
== 1 ? "" : "s");
3976 for (i
= 0; i
< mb
; i
++)
3978 origins
[dr
+ i
] = dr
+ i
;
3983 /* Any registers marked with that reg as an origin are reset. */
3984 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3985 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3992 /* Special case - our MUL patterns uses AX and sometimes BC. */
3993 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3996 fprintf (dump_file
, "Resetting origin of AX/BC for MUL pattern.\n");
3998 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3999 if (i
<= 3 || origins
[i
] <= 3)
4005 else if (get_attr_valloc (insn
) == VALLOC_DIVHI
)
4008 fprintf (dump_file
, "Resetting origin of AX/DE for DIVHI pattern.\n");
4010 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4015 || origins
[i
] == A_REG
4016 || origins
[i
] == X_REG
4017 || origins
[i
] == D_REG
4018 || origins
[i
] == E_REG
)
4024 else if (get_attr_valloc (insn
) == VALLOC_DIVSI
)
4027 fprintf (dump_file
, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
4029 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4030 if (i
<= 7 || origins
[i
] <= 7)
4037 if (GET_CODE (src
) == ASHIFT
4038 || GET_CODE (src
) == ASHIFTRT
4039 || GET_CODE (src
) == LSHIFTRT
)
4041 rtx count
= XEXP (src
, 1);
4043 if (GET_CODE (count
) == REG
)
4045 /* Special case - our pattern clobbers the count register. */
4046 int r
= REGNO (count
);
4049 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
4051 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4052 if (i
== r
|| origins
[i
] == r
)
4061 /* The idea behind this optimization is to look for cases where we
4062 move data from A to B to C, and instead move from A to B, and A to
4063 C. If B is a virtual register or memory, this is a big win on its
4064 own. If B turns out to be unneeded after this, it's a bigger win.
4065 For each register, we try to determine where it's value originally
4066 came from, if it's propogated purely through moves (and not
4067 computes). The ORIGINS[] array has the regno for the "origin" of
4068 the value in the [regno] it's indexed by. */
4070 rl78_propogate_register_origins (void)
4072 int origins
[FIRST_PSEUDO_REGISTER
];
4073 int age
[FIRST_PSEUDO_REGISTER
];
4075 rtx_insn
*insn
, *ninsn
= NULL
;
4078 reset_origins (origins
, age
);
4080 for (insn
= get_insns (); insn
; insn
= ninsn
)
4082 ninsn
= next_nonnote_nondebug_insn (insn
);
4086 fprintf (dump_file
, "\n");
4087 fprintf (dump_file
, "Origins:");
4088 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4089 if (origins
[i
] != i
)
4090 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
4091 fprintf (dump_file
, "\n");
4092 print_rtl_single (dump_file
, insn
);
4095 switch (GET_CODE (insn
))
4101 reset_origins (origins
, age
);
4108 pat
= PATTERN (insn
);
4110 if (GET_CODE (pat
) == PARALLEL
)
4112 rtx clobber
= XVECEXP (pat
, 0, 1);
4113 pat
= XVECEXP (pat
, 0, 0);
4114 if (GET_CODE (clobber
) == CLOBBER
4115 && GET_CODE (XEXP (clobber
, 0)) == REG
)
4117 int cr
= REGNO (XEXP (clobber
, 0));
4118 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
4120 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
4121 for (i
= 0; i
< mb
; i
++)
4123 origins
[cr
+ i
] = cr
+ i
;
4127 /* This happens with the DIV patterns. */
4128 else if (GET_CODE (clobber
) == SET
)
4130 set_origin (clobber
, insn
, origins
, age
);
4136 if (GET_CODE (pat
) == SET
)
4138 set_origin (pat
, insn
, origins
, age
);
4140 else if (GET_CODE (pat
) == CLOBBER
4141 && GET_CODE (XEXP (pat
, 0)) == REG
)
4143 if (REG_P (XEXP (pat
, 0)))
4145 unsigned int reg
= REGNO (XEXP (pat
, 0));
4155 /* Remove any SETs where the destination is unneeded. */
4157 rl78_remove_unused_sets (void)
4159 rtx_insn
*insn
, *ninsn
= NULL
;
4162 for (insn
= get_insns (); insn
; insn
= ninsn
)
4164 ninsn
= next_nonnote_nondebug_insn (insn
);
4166 rtx set
= single_set (insn
);
4170 dest
= SET_DEST (set
);
4172 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
4175 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
4178 fprintf (dump_file
, "deleting because the set register is never used.\n");
4184 /* This is the top of the devritualization pass. */
4188 /* split2 only happens when optimizing, but we need all movSIs to be
4193 rl78_alloc_physical_registers ();
4197 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4198 print_rtl_with_bb (dump_file
, get_insns (), 0);
4201 rl78_propogate_register_origins ();
4202 rl78_calculate_death_notes ();
4206 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4207 print_rtl_with_bb (dump_file
, get_insns (), 0);
4208 fprintf (dump_file
, "\n======================================================================\n");
4211 rl78_remove_unused_sets ();
4213 /* The code after devirtualizing has changed so much that at this point
4214 we might as well just rescan everything. Note that
4215 df_rescan_all_insns is not going to help here because it does not
4216 touch the artificial uses and defs. */
4217 df_finish_pass (true);
4219 df_live_add_problem ();
4220 df_scan_alloc (NULL
);
4227 #undef TARGET_RETURN_IN_MEMORY
4228 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4231 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
4233 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
4234 return (size
== -1 || size
> 8);
4238 #undef TARGET_RTX_COSTS
4239 #define TARGET_RTX_COSTS rl78_rtx_costs
4242 rl78_rtx_costs (rtx x
,
4244 int outer_code ATTRIBUTE_UNUSED
,
4245 int opno ATTRIBUTE_UNUSED
,
4247 bool speed ATTRIBUTE_UNUSED
)
4249 int code
= GET_CODE (x
);
4251 if (code
== IF_THEN_ELSE
)
4253 *total
= COSTS_N_INSNS (10);
4259 if (code
== MULT
&& ! speed
)
4261 * total
= COSTS_N_INSNS (8);
4273 /* If we are compiling for space then we do not want to use the
4274 inline SImode multiplication patterns or shift sequences.
4275 The cost is not set to 1 or 5 however as we have to allow for
4276 the possibility that we might be converting a leaf function
4277 into a non-leaf function. (There is no way to tell here).
4278 A value of 13 seems to be a reasonable compromise for the
4280 * total
= COSTS_N_INSNS (13);
4281 else if (RL78_MUL_G14
)
4282 *total
= COSTS_N_INSNS (14);
4283 else if (RL78_MUL_G13
)
4284 *total
= COSTS_N_INSNS (29);
4286 *total
= COSTS_N_INSNS (500);
4290 *total
= COSTS_N_INSNS (8);
4296 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4298 switch (INTVAL (XEXP (x
, 1)))
4300 case 0: *total
= COSTS_N_INSNS (0); break;
4301 case 1: *total
= COSTS_N_INSNS (6); break;
4302 case 2: case 3: case 4: case 5: case 6: case 7:
4303 *total
= COSTS_N_INSNS (10); break;
4304 case 8: *total
= COSTS_N_INSNS (6); break;
4305 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4306 *total
= COSTS_N_INSNS (10); break;
4307 case 16: *total
= COSTS_N_INSNS (3); break;
4308 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4309 *total
= COSTS_N_INSNS (4); break;
4310 case 24: *total
= COSTS_N_INSNS (4); break;
4311 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4312 *total
= COSTS_N_INSNS (5); break;
4316 *total
= COSTS_N_INSNS (10+4*16);
4327 static GTY(()) section
* saddr_section
;
4328 static GTY(()) section
* frodata_section
;
4331 rl78_saddr_p (rtx x
)
4337 if (GET_CODE (x
) == PLUS
)
4339 if (GET_CODE (x
) != SYMBOL_REF
)
4343 if (memcmp (c
, "@s.", 3) == 0)
4354 if (GET_CODE (x
) != CONST_INT
)
4357 if ((INTVAL (x
) & 0xFF00) != 0xFF00)
4363 #undef TARGET_STRIP_NAME_ENCODING
4364 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4367 rl78_strip_name_encoding (const char * sym
)
4373 else if (*sym
== '@' && sym
[2] == '.')
4380 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4381 is important if the stripped name is going to be passed to assemble_name()
4382 as that handles asterisk prefixed names in a special manner. */
4385 rl78_strip_nonasm_name_encoding (const char * sym
)
4389 if (*sym
== '@' && sym
[2] == '.')
4398 rl78_attrlist_to_encoding (tree list
, tree decl ATTRIBUTE_UNUSED
)
4402 if (is_attribute_p ("saddr", TREE_PURPOSE (list
)))
4404 list
= TREE_CHAIN (list
);
4410 #define RL78_ATTRIBUTES(decl) \
4411 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4412 : DECL_ATTRIBUTES (decl) \
4413 ? (DECL_ATTRIBUTES (decl)) \
4414 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4416 #undef TARGET_ENCODE_SECTION_INFO
4417 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4420 rl78_encode_section_info (tree decl
, rtx rtl
, int first
)
4423 const char * oldname
;
4428 tree rl78_attributes
;
4433 rtlname
= XEXP (rtl
, 0);
4435 if (GET_CODE (rtlname
) == SYMBOL_REF
)
4436 oldname
= XSTR (rtlname
, 0);
4437 else if (GET_CODE (rtlname
) == MEM
4438 && GET_CODE (XEXP (rtlname
, 0)) == SYMBOL_REF
)
4439 oldname
= XSTR (XEXP (rtlname
, 0), 0);
4443 type
= TREE_TYPE (decl
);
4444 if (type
== error_mark_node
)
4446 if (! DECL_P (decl
))
4448 rl78_attributes
= RL78_ATTRIBUTES (decl
);
4450 encoding
= rl78_attrlist_to_encoding (rl78_attributes
, decl
);
4454 newname
= (char *) alloca (strlen (oldname
) + 4);
4455 sprintf (newname
, "@%c.%s", encoding
, oldname
);
4456 idp
= get_identifier (newname
);
4458 gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (idp
));
4459 SYMBOL_REF_WEAK (XEXP (rtl
, 0)) = DECL_WEAK (decl
);
4460 SET_SYMBOL_REF_DECL (XEXP (rtl
, 0), decl
);
4464 #undef TARGET_ASM_INIT_SECTIONS
4465 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4468 rl78_asm_init_sections (void)
4471 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4472 "\t.section .saddr,\"aw\",@progbits");
4474 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4475 "\t.section .frodata,\"aw\",@progbits");
4478 #undef TARGET_ASM_SELECT_SECTION
4479 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4482 rl78_select_section (tree decl
,
4484 unsigned HOST_WIDE_INT align
)
4488 switch (TREE_CODE (decl
))
4491 if (!TREE_READONLY (decl
)
4492 || TREE_SIDE_EFFECTS (decl
)
4493 || !DECL_INITIAL (decl
)
4494 || (DECL_INITIAL (decl
) != error_mark_node
4495 && !TREE_CONSTANT (DECL_INITIAL (decl
))))
4499 if (! TREE_CONSTANT (decl
))
4507 if (TREE_CODE (decl
) == VAR_DECL
)
4509 const char *name
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
4511 if (name
[0] == '@' && name
[2] == '.')
4515 return saddr_section
;
4518 if (TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_FAR
4521 return frodata_section
;
4526 return TARGET_ES0
? frodata_section
: readonly_data_section
;
4528 switch (categorize_decl_for_section (decl
, reloc
))
4530 case SECCAT_TEXT
: return text_section
;
4531 case SECCAT_DATA
: return data_section
;
4532 case SECCAT_BSS
: return bss_section
;
4533 case SECCAT_RODATA
: return TARGET_ES0
? frodata_section
: readonly_data_section
;
4535 return default_select_section (decl
, reloc
, align
);
4540 rl78_output_labelref (FILE *file
, const char *str
)
4544 str2
= targetm
.strip_name_encoding (str
);
4546 fputs (user_label_prefix
, file
);
4551 rl78_output_aligned_common (FILE *stream
,
4552 tree decl ATTRIBUTE_UNUSED
,
4554 int size
, int align
, int global
)
4556 /* We intentionally don't use rl78_section_tag() here. */
4557 if (name
[0] == '@' && name
[2] == '.')
4559 const char *sec
= 0;
4563 switch_to_section (saddr_section
);
4572 while (align
> BITS_PER_UNIT
)
4577 name2
= targetm
.strip_name_encoding (name
);
4579 fprintf (stream
, "\t.global\t_%s\n", name2
);
4580 fprintf (stream
, "\t.p2align %d\n", p2align
);
4581 fprintf (stream
, "\t.type\t_%s,@object\n", name2
);
4582 fprintf (stream
, "\t.size\t_%s,%d\n", name2
, size
);
4583 fprintf (stream
, "_%s:\n\t.zero\t%d\n", name2
, size
);
4590 fprintf (stream
, "\t.local\t");
4591 assemble_name (stream
, name
);
4592 fprintf (stream
, "\n");
4594 fprintf (stream
, "\t.comm\t");
4595 assemble_name (stream
, name
);
4596 fprintf (stream
, ",%u,%u\n", size
, align
/ BITS_PER_UNIT
);
4599 #undef TARGET_INSERT_ATTRIBUTES
4600 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4603 rl78_insert_attributes (tree decl
, tree
*attributes ATTRIBUTE_UNUSED
)
4606 && TREE_CODE (decl
) == VAR_DECL
4607 && TREE_READONLY (decl
)
4608 && TREE_ADDRESSABLE (decl
)
4609 && TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_GENERIC
)
4611 tree type
= TREE_TYPE (decl
);
4612 tree attr
= TYPE_ATTRIBUTES (type
);
4613 int q
= TYPE_QUALS_NO_ADDR_SPACE (type
) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR
);
4615 TREE_TYPE (decl
) = build_type_attribute_qual_variant (type
, attr
, q
);
4619 #undef TARGET_ASM_INTEGER
4620 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4623 rl78_asm_out_integer (rtx x
, unsigned int size
, int aligned_p
)
4625 if (default_assemble_integer (x
, size
, aligned_p
))
4630 assemble_integer_with_op (".long\t", x
);
4637 #undef TARGET_UNWIND_WORD_MODE
4638 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4641 rl78_unwind_word_mode (void)
4646 #ifndef USE_COLLECT2
4647 #undef TARGET_ASM_CONSTRUCTOR
4648 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4649 #undef TARGET_ASM_DESTRUCTOR
4650 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4653 rl78_asm_ctor_dtor (rtx symbol
, int priority
, bool is_ctor
)
4657 if (priority
!= DEFAULT_INIT_PRIORITY
)
4659 /* This section of the function is based upon code copied
4660 from: gcc/varasm.c:get_cdtor_priority_section(). */
4663 sprintf (buf
, "%s.%.5u", is_ctor
? ".ctors" : ".dtors",
4664 MAX_INIT_PRIORITY
- priority
);
4665 sec
= get_section (buf
, 0, NULL
);
4668 sec
= is_ctor
? ctors_section
: dtors_section
;
4670 assemble_addr_to_section (symbol
, sec
);
4674 rl78_asm_constructor (rtx symbol
, int priority
)
4676 rl78_asm_ctor_dtor (symbol
, priority
, true);
4680 rl78_asm_destructor (rtx symbol
, int priority
)
4682 rl78_asm_ctor_dtor (symbol
, priority
, false);
4684 #endif /* ! USE_COLLECT2 */
4686 /* Scan backwards through the insn chain looking to see if the flags
4687 have been set for a comparison of OP against OPERAND. Start with
4688 the insn *before* the current insn. */
4691 rl78_flags_already_set (rtx op
, rtx operand
)
4693 /* We only track the Z flag. */
4694 if (GET_CODE (op
) != EQ
&& GET_CODE (op
) != NE
)
4697 /* This should not happen, but let's be paranoid. */
4698 if (current_output_insn
== NULL_RTX
)
4704 for (insn
= prev_nonnote_nondebug_insn (current_output_insn
);
4706 insn
= prev_nonnote_nondebug_insn (insn
))
4711 if (! INSN_P (insn
))
4714 /* Make sure that the insn can be recognized. */
4715 if (recog_memoized (insn
) == -1)
4718 enum attr_update_Z updated
= get_attr_update_Z (insn
);
4720 rtx set
= single_set (insn
);
4721 bool must_break
= (set
!= NULL_RTX
&& rtx_equal_p (operand
, SET_DEST (set
)));
4727 case UPDATE_Z_CLOBBER
:
4730 case UPDATE_Z_UPDATE_Z
:
4742 /* We have to re-recognize the current insn as the call(s) to
4743 get_attr_update_Z() above will have overwritten the recog_data cache. */
4744 recog_memoized (current_output_insn
);
4745 cleanup_subreg_operands (current_output_insn
);
4746 constrain_operands_cached (current_output_insn
, 1);
4752 rl78_addsi3_internal (rtx
* operands
, unsigned int alternative
)
4754 /* If we are adding in a constant symbolic address when -mes0
4755 is active then we know that the address must be <64K and
4756 that it is invalid to access anything above 64K relative to
4757 this address. So we can skip adding in the high bytes. */
4759 && GET_CODE (operands
[2]) == SYMBOL_REF
4760 && TREE_CODE (SYMBOL_REF_DECL (operands
[2])) == VAR_DECL
4761 && TREE_READONLY (SYMBOL_REF_DECL (operands
[2]))
4762 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands
[2])))
4763 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
4765 switch (alternative
)
4769 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";
4771 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";
4778 #undef TARGET_PREFERRED_RELOAD_CLASS
4779 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4782 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t rclass
)
4784 if (rclass
== NO_REGS
)
4791 struct gcc_target targetm
= TARGET_INITIALIZER
;
4793 #include "gt-rl78.h"