1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2015 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "fold-const.h"
30 #include "stor-layout.h"
34 #include "hard-reg-set.h"
35 #include "insn-config.h"
36 #include "conditions.h"
38 #include "insn-attr.h"
47 #include "insn-codes.h"
51 #include "diagnostic-core.h"
54 #include "dominance.h"
60 #include "cfgcleanup.h"
62 #include "basic-block.h"
67 #include "langhooks.h"
68 #include "rl78-protos.h"
70 #include "tree-pass.h"
72 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
73 #include "insn-flags.h" /* for gen_*(). */
75 #include "stringpool.h"
77 #include "target-def.h"
79 static inline bool is_interrupt_func (const_tree decl
);
80 static inline bool is_brk_interrupt_func (const_tree decl
);
81 static void rl78_reorg (void);
82 static const char *rl78_strip_name_encoding (const char *);
83 static const char *rl78_strip_nonasm_name_encoding (const char *);
84 static section
* rl78_select_section (tree
, int, unsigned HOST_WIDE_INT
);
87 /* Debugging statements are tagged with DEBUG0 only so that they can
88 be easily enabled individually, by replacing the '0' with '1' as
93 /* REGISTER_NAMES has the names for individual 8-bit registers, but
94 these have the names we need to use when referring to 16-bit
96 static const char * const word_regnames
[] =
98 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
99 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
100 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
101 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
102 "sp", "ap", "psw", "es", "cs"
105 struct GTY(()) machine_function
107 /* If set, the rest of the fields have been computed. */
109 /* Which register pairs need to be pushed in the prologue. */
110 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
112 /* These fields describe the frame layout... */
114 /* 4 bytes for saved PC */
117 int framesize_locals
;
118 int framesize_outgoing
;
122 /* If set, recog is allowed to match against the "real" patterns. */
124 /* If set, recog is allowed to match against the "virtual" patterns. */
126 /* Set if the current function needs to clean up any trampolines. */
127 int trampolines_used
;
128 /* True if the ES register is used and hence
129 needs to be saved inside interrupt handlers. */
133 /* This is our init_machine_status, as set in
134 rl78_option_override. */
135 static struct machine_function
*
136 rl78_init_machine_status (void)
138 struct machine_function
*m
;
140 m
= ggc_cleared_alloc
<machine_function
> ();
141 m
->virt_insns_ok
= 1;
146 /* This pass converts virtual instructions using virtual registers, to
147 real instructions using real registers. Rather than run it as
148 reorg, we reschedule it before vartrack to help with debugging. */
151 const pass_data pass_data_rl78_devirt
=
155 OPTGROUP_NONE
, /* optinfo_flags */
156 TV_MACH_DEP
, /* tv_id */
157 0, /* properties_required */
158 0, /* properties_provided */
159 0, /* properties_destroyed */
160 0, /* todo_flags_start */
161 0, /* todo_flags_finish */
164 class pass_rl78_devirt
: public rtl_opt_pass
167 pass_rl78_devirt (gcc::context
*ctxt
)
168 : rtl_opt_pass (pass_data_rl78_devirt
, ctxt
)
172 /* opt_pass methods: */
173 virtual unsigned int execute (function
*)
182 make_pass_rl78_devirt (gcc::context
*ctxt
)
184 return new pass_rl78_devirt (ctxt
);
187 /* Redundant move elimination pass. Must be run after the basic block
188 reordering pass for the best effect. */
191 move_elim_pass (void)
193 rtx_insn
*insn
, *ninsn
;
196 for (insn
= get_insns (); insn
; insn
= ninsn
)
200 ninsn
= next_nonnote_nondebug_insn (insn
);
202 if ((set
= single_set (insn
)) == NULL_RTX
)
208 /* If we have two SET insns in a row (without anything
209 between them) and the source of the second one is the
210 destination of the first one, and vice versa, then we
211 can eliminate the second SET. */
213 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
214 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
215 /* ... and none of the operands are volatile. */
216 && ! volatile_refs_p (SET_SRC (prev
))
217 && ! volatile_refs_p (SET_DEST (prev
))
218 && ! volatile_refs_p (SET_SRC (set
))
219 && ! volatile_refs_p (SET_DEST (set
)))
222 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
233 print_rtl_with_bb (dump_file
, get_insns (), 0);
240 const pass_data pass_data_rl78_move_elim
=
243 "move_elim", /* name */
244 OPTGROUP_NONE
, /* optinfo_flags */
245 TV_MACH_DEP
, /* tv_id */
246 0, /* properties_required */
247 0, /* properties_provided */
248 0, /* properties_destroyed */
249 0, /* todo_flags_start */
250 0, /* todo_flags_finish */
253 class pass_rl78_move_elim
: public rtl_opt_pass
256 pass_rl78_move_elim (gcc::context
*ctxt
)
257 : rtl_opt_pass (pass_data_rl78_move_elim
, ctxt
)
261 /* opt_pass methods: */
262 virtual unsigned int execute (function
*) { return move_elim_pass (); }
267 make_pass_rl78_move_elim (gcc::context
*ctxt
)
269 return new pass_rl78_move_elim (ctxt
);
272 #undef TARGET_ASM_FILE_START
273 #define TARGET_ASM_FILE_START rl78_asm_file_start
276 rl78_asm_file_start (void)
282 /* The memory used is 0xffec8 to 0xffedf; real registers are in
283 0xffee0 to 0xffee7. */
284 for (i
= 8; i
< 32; i
++)
285 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
289 for (i
= 0; i
< 8; i
++)
291 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
292 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
293 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
297 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
298 struct register_pass_info rl78_devirt_info
=
303 PASS_POS_INSERT_BEFORE
306 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
307 struct register_pass_info rl78_move_elim_info
=
312 PASS_POS_INSERT_AFTER
315 register_pass (& rl78_devirt_info
);
316 register_pass (& rl78_move_elim_info
);
320 rl78_output_symbol_ref (FILE * file
, rtx sym
)
322 tree type
= SYMBOL_REF_DECL (sym
);
323 const char *str
= XSTR (sym
, 0);
327 fputs (str
+ 1, file
);
331 str
= rl78_strip_nonasm_name_encoding (str
);
332 if (type
&& TREE_CODE (type
) == FUNCTION_DECL
)
334 fprintf (file
, "%%code(");
335 assemble_name (file
, str
);
339 assemble_name (file
, str
);
343 #undef TARGET_OPTION_OVERRIDE
344 #define TARGET_OPTION_OVERRIDE rl78_option_override
347 rl78_option_override (void)
349 flag_omit_frame_pointer
= 1;
350 flag_no_function_cse
= 1;
351 flag_split_wide_types
= 0;
353 init_machine_status
= rl78_init_machine_status
;
359 for (i
= 24; i
< 32; i
++)
364 && strcmp (lang_hooks
.name
, "GNU C")
365 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
366 && strcmp (lang_hooks
.name
, "GNU GIMPLE"))
367 /* Address spaces are currently only supported by C. */
368 error ("-mes0 can only be used with C");
370 switch (rl78_cpu_type
)
373 rl78_cpu_type
= CPU_G14
;
374 if (rl78_mul_type
== MUL_UNINIT
)
375 rl78_mul_type
= MUL_NONE
;
379 switch (rl78_mul_type
)
381 case MUL_UNINIT
: rl78_mul_type
= MUL_NONE
; break;
382 case MUL_NONE
: break;
383 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
384 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
389 switch (rl78_mul_type
)
391 case MUL_UNINIT
: rl78_mul_type
= MUL_G13
; break;
392 case MUL_NONE
: break;
394 /* The S2 core does not have mul/div instructions. */
395 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
400 switch (rl78_mul_type
)
402 case MUL_UNINIT
: rl78_mul_type
= MUL_G14
; break;
403 case MUL_NONE
: break;
405 /* The G14 core does not have the hardware multiply peripheral used by the
406 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
407 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
413 /* Most registers are 8 bits. Some are 16 bits because, for example,
414 gcc doesn't like dealing with $FP as a register pair (the second
415 half of $fp is also 2 to keep reload happy wrt register pairs, but
416 no register class includes it). This table maps register numbers
418 static const int register_sizes
[] =
420 1, 1, 1, 1, 1, 1, 1, 1,
421 1, 1, 1, 1, 1, 1, 1, 1,
422 1, 1, 1, 1, 1, 1, 2, 2,
423 1, 1, 1, 1, 1, 1, 1, 1,
427 /* Predicates used in the MD patterns. This one is true when virtual
428 insns may be matched, which typically means before (or during) the
431 rl78_virt_insns_ok (void)
434 return cfun
->machine
->virt_insns_ok
;
438 /* Predicates used in the MD patterns. This one is true when real
439 insns may be matched, which typically means after (or during) the
442 rl78_real_insns_ok (void)
445 return cfun
->machine
->real_insns_ok
;
449 /* Implements HARD_REGNO_NREGS. */
451 rl78_hard_regno_nregs (int regno
, machine_mode mode
)
453 int rs
= register_sizes
[regno
];
456 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
459 /* Implements HARD_REGNO_MODE_OK. */
461 rl78_hard_regno_mode_ok (int regno
, machine_mode mode
)
463 int s
= GET_MODE_SIZE (mode
);
467 /* These are not to be used by gcc. */
468 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
470 /* $fp can always be accessed as a 16-bit value. */
471 if (regno
== FP_REG
&& s
== 2)
475 /* Since a reg-reg move is really a reg-mem move, we must
476 enforce alignment. */
477 if (s
> 1 && (regno
% 2))
482 return (mode
== BImode
);
483 /* All other registers must be accessed in their natural sizes. */
484 if (s
== register_sizes
[regno
])
489 /* Simplify_gen_subreg() doesn't handle memory references the way we
490 need it to below, so we use this function for when we must get a
491 valid subreg in a "natural" state. */
493 rl78_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
495 if (GET_CODE (r
) == MEM
)
496 return adjust_address (r
, mode
, byte
);
498 return simplify_gen_subreg (mode
, r
, omode
, byte
);
501 /* Used by movsi. Split SImode moves into two HImode moves, using
502 appropriate patterns for the upper and lower halves of symbols. */
504 rl78_expand_movsi (rtx
*operands
)
506 rtx op00
, op02
, op10
, op12
;
508 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
509 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
510 if (GET_CODE (operands
[1]) == CONST
511 || GET_CODE (operands
[1]) == SYMBOL_REF
)
513 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
514 op10
= gen_rtx_CONST (HImode
, op10
);
515 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
516 op12
= gen_rtx_CONST (HImode
, op12
);
520 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
521 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
524 if (rtx_equal_p (operands
[0], operands
[1]))
526 else if (rtx_equal_p (op00
, op12
))
528 emit_move_insn (op02
, op12
);
529 emit_move_insn (op00
, op10
);
533 emit_move_insn (op00
, op10
);
534 emit_move_insn (op02
, op12
);
538 /* Generate code to move an SImode value. */
540 rl78_split_movsi (rtx
*operands
, enum machine_mode omode
)
542 rtx op00
, op02
, op10
, op12
;
544 op00
= rl78_subreg (HImode
, operands
[0], omode
, 0);
545 op02
= rl78_subreg (HImode
, operands
[0], omode
, 2);
547 if (GET_CODE (operands
[1]) == CONST
548 || GET_CODE (operands
[1]) == SYMBOL_REF
)
550 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
551 op10
= gen_rtx_CONST (HImode
, op10
);
552 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
553 op12
= gen_rtx_CONST (HImode
, op12
);
557 op10
= rl78_subreg (HImode
, operands
[1], omode
, 0);
558 op12
= rl78_subreg (HImode
, operands
[1], omode
, 2);
561 if (rtx_equal_p (operands
[0], operands
[1]))
563 else if (rtx_equal_p (op00
, op12
))
579 /* Used by various two-operand expanders which cannot accept all
580 operands in the "far" namespace. Force some such operands into
581 registers so that each pattern has at most one far operand. */
583 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
588 /* FIXME: in the future, be smarter about only doing this if the
589 other operand is also far, assuming the devirtualizer can also
591 if (rl78_far_p (operands
[0]))
593 temp_reg
= operands
[0];
594 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
600 emit_insn (gen (operands
[0], operands
[1]));
602 emit_move_insn (temp_reg
, operands
[0]);
606 /* Likewise, but for three-operand expanders. */
608 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
613 /* As an exception, we allow two far operands if they're identical
614 and the third operand is not a MEM. This allows global variables
615 to be incremented, for example. */
616 if (rtx_equal_p (operands
[0], operands
[1])
617 && ! MEM_P (operands
[2]))
620 /* FIXME: Likewise. */
621 if (rl78_far_p (operands
[1]))
623 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
624 emit_move_insn (temp_reg
, operands
[1]);
625 operands
[1] = temp_reg
;
628 if (rl78_far_p (operands
[0]))
630 temp_reg
= operands
[0];
631 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
637 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
639 emit_move_insn (temp_reg
, operands
[0]);
643 #undef TARGET_CAN_ELIMINATE
644 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
647 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
652 /* Returns true if the given register needs to be saved by the
655 need_to_save (unsigned int regno
)
657 if (is_interrupt_func (cfun
->decl
))
659 /* We don't know what devirt will need */
663 /* We don't need to save registers that have
664 been reserved for interrupt handlers. */
668 /* If the handler is a non-leaf function then it may call
669 non-interrupt aware routines which will happily clobber
670 any call_used registers, so we have to preserve them.
671 We do not have to worry about the frame pointer register
672 though, as that is handled below. */
673 if (!crtl
->is_leaf
&& call_used_regs
[regno
] && regno
< 22)
676 /* Otherwise we only have to save a register, call_used
677 or not, if it is used by this handler. */
678 return df_regs_ever_live_p (regno
);
681 if (regno
== FRAME_POINTER_REGNUM
682 && (frame_pointer_needed
|| df_regs_ever_live_p (regno
)))
684 if (fixed_regs
[regno
])
686 if (crtl
->calls_eh_return
)
688 if (df_regs_ever_live_p (regno
)
689 && !call_used_regs
[regno
])
694 /* We use this to wrap all emitted insns in the prologue. */
698 RTX_FRAME_RELATED_P (x
) = 1;
702 /* Compute all the frame-related fields in our machine_function
705 rl78_compute_frame_info (void)
709 cfun
->machine
->computed
= 1;
710 cfun
->machine
->framesize_regs
= 0;
711 cfun
->machine
->framesize_locals
= get_frame_size ();
712 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
714 for (i
= 0; i
< 16; i
++)
715 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
717 cfun
->machine
->need_to_push
[i
] = 1;
718 cfun
->machine
->framesize_regs
+= 2;
721 cfun
->machine
->need_to_push
[i
] = 0;
723 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
724 cfun
->machine
->framesize_locals
++;
726 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
727 + cfun
->machine
->framesize_locals
728 + cfun
->machine
->framesize_outgoing
);
731 /* Returns true if the provided function has the specified attribute. */
733 has_func_attr (const_tree decl
, const char * func_attr
)
735 if (decl
== NULL_TREE
)
736 decl
= current_function_decl
;
738 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
741 /* Returns true if the provided function has the "interrupt" attribute. */
743 is_interrupt_func (const_tree decl
)
745 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
748 /* Returns true if the provided function has the "brk_interrupt" attribute. */
750 is_brk_interrupt_func (const_tree decl
)
752 return has_func_attr (decl
, "brk_interrupt");
755 /* Check "interrupt" attributes. */
757 rl78_handle_func_attribute (tree
* node
,
760 int flags ATTRIBUTE_UNUSED
,
763 gcc_assert (DECL_P (* node
));
764 gcc_assert (args
== NULL_TREE
);
766 if (TREE_CODE (* node
) != FUNCTION_DECL
)
768 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
770 * no_add_attrs
= true;
773 /* FIXME: We ought to check that the interrupt and exception
774 handler attributes have been applied to void functions. */
778 /* Check "naked" attributes. */
780 rl78_handle_naked_attribute (tree
* node
,
781 tree name ATTRIBUTE_UNUSED
,
783 int flags ATTRIBUTE_UNUSED
,
786 gcc_assert (DECL_P (* node
));
787 gcc_assert (args
== NULL_TREE
);
789 if (TREE_CODE (* node
) != FUNCTION_DECL
)
791 warning (OPT_Wattributes
, "naked attribute only applies to functions");
792 * no_add_attrs
= true;
795 /* Disable warnings about this function - eg reaching the end without
796 seeing a return statement - because the programmer is doing things
797 that gcc does not know about. */
798 TREE_NO_WARNING (* node
) = 1;
803 /* Check "saddr" attributes. */
805 rl78_handle_saddr_attribute (tree
* node
,
807 tree args ATTRIBUTE_UNUSED
,
808 int flags ATTRIBUTE_UNUSED
,
811 gcc_assert (DECL_P (* node
));
813 if (TREE_CODE (* node
) == FUNCTION_DECL
)
815 warning (OPT_Wattributes
, "%qE attribute doesn't apply to functions",
817 * no_add_attrs
= true;
823 #undef TARGET_ATTRIBUTE_TABLE
824 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
826 /* Table of RL78-specific attributes. */
827 const struct attribute_spec rl78_attribute_table
[] =
829 /* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
830 affects_type_identity. */
831 { "interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
833 { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute
,
835 { "naked", 0, 0, true, false, false, rl78_handle_naked_attribute
,
837 { "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute
,
839 { NULL
, 0, 0, false, false, false, NULL
, false }
844 /* Break down an address RTX into its component base/index/addend
845 portions and return TRUE if the address is of a valid form, else
848 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
854 if (GET_CODE (x
) == UNSPEC
855 && XINT (x
, 1) == UNS_ES_ADDR
)
856 x
= XVECEXP (x
, 0, 1);
858 if (GET_CODE (x
) == REG
)
864 /* We sometimes get these without the CONST wrapper */
865 if (GET_CODE (x
) == PLUS
866 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
867 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
873 if (GET_CODE (x
) == PLUS
)
878 if (GET_CODE (*base
) == SUBREG
)
880 if (GET_MODE (*base
) == HImode
881 && GET_MODE (XEXP (*base
, 0)) == SImode
882 && GET_CODE (XEXP (*base
, 0)) == REG
)
884 /* This is a throw-away rtx just to tell everyone
885 else what effective register we're using. */
886 *base
= gen_rtx_REG (HImode
, REGNO (XEXP (*base
, 0)));
890 if (GET_CODE (*base
) != REG
891 && GET_CODE (x
) == REG
)
898 if (GET_CODE (*base
) != REG
)
901 if (GET_CODE (x
) == ZERO_EXTEND
902 && GET_CODE (XEXP (x
, 0)) == REG
)
904 *index
= XEXP (x
, 0);
909 switch (GET_CODE (x
))
912 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
913 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
924 switch (GET_CODE (XEXP (x
, 0)))
948 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
951 rl78_hl_b_c_addr_p (rtx op
)
955 if (GET_CODE (op
) != PLUS
)
959 if (GET_CODE (hl
) == ZERO_EXTEND
)
965 if (GET_CODE (hl
) != REG
)
967 if (GET_CODE (bc
) != ZERO_EXTEND
)
970 if (GET_CODE (bc
) != REG
)
972 if (REGNO (hl
) != HL_REG
)
974 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
980 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
982 /* Return the appropriate mode for a named address address. */
984 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
985 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
987 static enum machine_mode
988 rl78_addr_space_address_mode (addr_space_t addrspace
)
992 case ADDR_SPACE_GENERIC
:
994 case ADDR_SPACE_NEAR
:
1003 /* Used in various constraints and predicates to match operands in the
1004 "far" address space. */
1011 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx (x
);
1012 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
1015 /* Not all far addresses are legitimate, because the devirtualizer
1016 can't handle them. */
1017 if (! rl78_as_legitimate_address (GET_MODE (x
), XEXP (x
, 0), false, ADDR_SPACE_FAR
))
1020 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x
))) == 32;
1023 /* Return the appropriate mode for a named address pointer. */
1024 #undef TARGET_ADDR_SPACE_POINTER_MODE
1025 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1028 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
1032 case ADDR_SPACE_GENERIC
:
1034 case ADDR_SPACE_NEAR
:
1036 case ADDR_SPACE_FAR
:
1043 /* Returns TRUE for valid addresses. */
1044 #undef TARGET_VALID_POINTER_MODE
1045 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1048 rl78_valid_pointer_mode (machine_mode m
)
1050 return (m
== HImode
|| m
== SImode
);
1053 #undef TARGET_LEGITIMATE_CONSTANT_P
1054 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1057 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
1062 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1063 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1066 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
1067 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
1069 rtx base
, index
, addend
;
1070 bool is_far_addr
= false;
1073 as_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (as
));
1075 if (GET_CODE (x
) == UNSPEC
1076 && XINT (x
, 1) == UNS_ES_ADDR
)
1078 x
= XVECEXP (x
, 0, 1);
1082 if (as_bits
== 16 && is_far_addr
)
1085 if (! characterize_address (x
, &base
, &index
, &addend
))
1088 /* We can't extract the high/low portions of a PLUS address
1089 involving a register during devirtualization, so make sure all
1090 such __far addresses do not have addends. This forces GCC to do
1091 the sum separately. */
1092 if (addend
&& base
&& as_bits
== 32 && GET_MODE (base
) == SImode
)
1097 int ir
= REGNO (index
);
1098 int br
= REGNO (base
);
1100 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1101 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
1102 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
1106 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
1109 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
1110 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
1116 /* Determine if one named address space is a subset of another. */
1117 #undef TARGET_ADDR_SPACE_SUBSET_P
1118 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1121 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1126 subset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset
));
1127 superset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset
));
1129 return (subset_bits
<= superset_bits
);
1132 #undef TARGET_ADDR_SPACE_CONVERT
1133 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1135 /* Convert from one address space to another. */
1137 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1139 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1140 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1145 to_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as
));
1146 from_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as
));
1148 if (to_bits
< from_bits
)
1151 /* This is unpredictable, as we're truncating off usable address
1154 warning (OPT_Waddress
, "converting far pointer to near pointer");
1155 result
= gen_reg_rtx (HImode
);
1156 if (GET_CODE (op
) == SYMBOL_REF
1157 || (GET_CODE (op
) == REG
&& REGNO (op
) >= FIRST_PSEUDO_REGISTER
))
1158 tmp
= gen_rtx_raw_SUBREG (HImode
, op
, 0);
1160 tmp
= simplify_subreg (HImode
, op
, SImode
, 0);
1161 gcc_assert (tmp
!= NULL_RTX
);
1162 emit_move_insn (result
, tmp
);
1165 else if (to_bits
> from_bits
)
1167 /* This always works. */
1168 result
= gen_reg_rtx (SImode
);
1169 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
1170 if (TREE_CODE (from_type
) == POINTER_TYPE
1171 && TREE_CODE (TREE_TYPE (from_type
)) == FUNCTION_TYPE
)
1172 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
1174 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), GEN_INT (0x0f));
1182 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1184 rl78_regno_mode_code_ok_for_base_p (int regno
, machine_mode mode ATTRIBUTE_UNUSED
,
1185 addr_space_t address_space ATTRIBUTE_UNUSED
,
1186 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
1188 if (regno
<= SP_REG
&& regno
>= 16)
1190 if (index_code
== REG
)
1191 return (regno
== HL_REG
);
1192 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
1197 /* Implements MODE_CODE_BASE_REG_CLASS. */
1199 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED
,
1200 addr_space_t address_space ATTRIBUTE_UNUSED
,
1201 int outer_code ATTRIBUTE_UNUSED
,
1202 int index_code ATTRIBUTE_UNUSED
)
1207 /* Typical stack layout should looks like this after the function's prologue:
1212 | | arguments saved | Increasing
1213 | | on the stack | addresses
1214 PARENT arg pointer -> | | /
1215 -------------------------- ---- -------------------
1216 CHILD |ret | return address
1221 frame pointer -> | | /
1229 | | outgoing | Decreasing
1230 | | arguments | addresses
1231 current stack pointer -> | | / |
1232 -------------------------- ---- ------------------ V
1235 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1236 described in the machine_Function struct definition, above. */
1238 rl78_initial_elimination_offset (int from
, int to
)
1240 int rv
= 0; /* as if arg to arg */
1242 rl78_compute_frame_info ();
1246 case STACK_POINTER_REGNUM
:
1247 rv
+= cfun
->machine
->framesize_outgoing
;
1248 rv
+= cfun
->machine
->framesize_locals
;
1250 case FRAME_POINTER_REGNUM
:
1251 rv
+= cfun
->machine
->framesize_regs
;
1260 case FRAME_POINTER_REGNUM
:
1262 rv
-= cfun
->machine
->framesize_regs
;
1263 case ARG_POINTER_REGNUM
:
1273 rl78_is_naked_func (void)
1275 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1278 /* Expand the function prologue (from the prologue pattern). */
1280 rl78_expand_prologue (void)
1283 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1284 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1287 if (rl78_is_naked_func ())
1290 /* Always re-compute the frame info - the register usage may have changed. */
1291 rl78_compute_frame_info ();
1293 if (flag_stack_usage_info
)
1294 current_function_static_stack_size
= cfun
->machine
->framesize
;
1296 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1297 for (i
= 0; i
< 4; i
++)
1298 if (cfun
->machine
->need_to_push
[i
])
1300 /* Select Bank 0 if we are using any registers from Bank 0. */
1301 emit_insn (gen_sel_rb (GEN_INT (0)));
1305 for (i
= 0; i
< 16; i
++)
1306 if (cfun
->machine
->need_to_push
[i
])
1314 emit_move_insn (ax
, gen_rtx_REG (HImode
, reg
));
1320 int need_bank
= i
/4;
1322 if (need_bank
!= rb
)
1324 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1329 F (emit_insn (gen_push (gen_rtx_REG (HImode
, reg
))));
1333 emit_insn (gen_sel_rb (GEN_INT (0)));
1335 /* Save ES register inside interrupt functions if it is used. */
1336 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1338 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode
, A_REG
)));
1339 F (emit_insn (gen_push (ax
)));
1342 if (frame_pointer_needed
)
1344 F (emit_move_insn (ax
, sp
));
1345 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
), ax
));
1348 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1351 /* If we need to subtract more than 254*3 then it is faster and
1352 smaller to move SP into AX and perform the subtraction there. */
1357 emit_move_insn (ax
, sp
);
1358 emit_insn (gen_subhi3 (ax
, ax
, GEN_INT (fs
)));
1359 insn
= F (emit_move_insn (sp
, ax
));
1360 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
1361 gen_rtx_SET (sp
, gen_rtx_PLUS (HImode
, sp
,
1368 int fs_byte
= (fs
> 254) ? 254 : fs
;
1370 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1377 /* Expand the function epilogue (from the epilogue pattern). */
1379 rl78_expand_epilogue (void)
1382 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1383 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1386 if (rl78_is_naked_func ())
1389 if (frame_pointer_needed
)
1391 emit_move_insn (ax
, gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1392 emit_move_insn (sp
, ax
);
1396 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1399 emit_move_insn (ax
, sp
);
1400 emit_insn (gen_addhi3 (ax
, ax
, GEN_INT (fs
)));
1401 emit_move_insn (sp
, ax
);
1407 int fs_byte
= (fs
> 254) ? 254 : fs
;
1409 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1415 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1417 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1418 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode
, A_REG
)));
1421 for (i
= 15; i
>= 0; i
--)
1422 if (cfun
->machine
->need_to_push
[i
])
1424 rtx dest
= gen_rtx_REG (HImode
, i
* 2);
1429 emit_insn (gen_pop (dest
));
1432 emit_insn (gen_pop (ax
));
1433 emit_move_insn (dest
, ax
);
1434 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1435 emit_insn (gen_use (dest
));
1440 int need_bank
= i
/ 4;
1442 if (need_bank
!= rb
)
1444 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1447 emit_insn (gen_pop (dest
));
1452 emit_insn (gen_sel_rb (GEN_INT (0)));
1454 if (cfun
->machine
->trampolines_used
)
1455 emit_insn (gen_trampoline_uninit ());
1457 if (is_brk_interrupt_func (cfun
->decl
))
1458 emit_jump_insn (gen_brk_interrupt_return ());
1459 else if (is_interrupt_func (cfun
->decl
))
1460 emit_jump_insn (gen_interrupt_return ());
1462 emit_jump_insn (gen_rl78_return ());
1465 /* Likewise, for exception handlers. */
1467 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1469 /* FIXME - replace this with an indirect jump with stack adjust. */
1470 emit_jump_insn (gen_rl78_return ());
1473 #undef TARGET_ASM_FUNCTION_PROLOGUE
1474 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1476 /* We don't use this to actually emit the function prologue. We use
1477 this to insert a comment in the asm file describing the
1480 rl78_start_function (FILE *file
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1484 if (cfun
->machine
->framesize
== 0)
1486 fprintf (file
, "\t; start of function\n");
1488 if (cfun
->machine
->framesize_regs
)
1490 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1491 for (i
= 0; i
< 16; i
++)
1492 if (cfun
->machine
->need_to_push
[i
])
1493 fprintf (file
, " %s", word_regnames
[i
*2]);
1494 fprintf (file
, "\n");
1497 if (frame_pointer_needed
)
1498 fprintf (file
, "\t; $fp points here (r22)\n");
1500 if (cfun
->machine
->framesize_locals
)
1501 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1502 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1504 if (cfun
->machine
->framesize_outgoing
)
1505 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1506 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1508 if (cfun
->machine
->uses_es
)
1509 fprintf (file
, "\t; uses ES register\n");
1512 /* Return an RTL describing where a function return value of type RET_TYPE
1515 #undef TARGET_FUNCTION_VALUE
1516 #define TARGET_FUNCTION_VALUE rl78_function_value
1519 rl78_function_value (const_tree ret_type
,
1520 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1521 bool outgoing ATTRIBUTE_UNUSED
)
1523 machine_mode mode
= TYPE_MODE (ret_type
);
1525 return gen_rtx_REG (mode
, 8);
1528 #undef TARGET_PROMOTE_FUNCTION_MODE
1529 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1532 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1534 int *punsignedp ATTRIBUTE_UNUSED
,
1535 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1540 /* Return an RTL expression describing the register holding a function
1541 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1542 be passed on the stack. CUM describes the previous parameters to the
1543 function and NAMED is false if the parameter is part of a variable
1544 parameter list, or the last named parameter before the start of a
1545 variable parameter list. */
1547 #undef TARGET_FUNCTION_ARG
1548 #define TARGET_FUNCTION_ARG rl78_function_arg
1551 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1552 machine_mode mode ATTRIBUTE_UNUSED
,
1553 const_tree type ATTRIBUTE_UNUSED
,
1554 bool named ATTRIBUTE_UNUSED
)
1559 #undef TARGET_FUNCTION_ARG_ADVANCE
1560 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1563 rl78_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
, const_tree type
,
1564 bool named ATTRIBUTE_UNUSED
)
1567 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1569 rounded_size
= ((mode
== BLKmode
)
1570 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1571 if (rounded_size
& 1)
1573 (*cum
) += rounded_size
;
1576 #undef TARGET_FUNCTION_ARG_BOUNDARY
1577 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1580 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED
,
1581 const_tree type ATTRIBUTE_UNUSED
)
1586 /* Supported modifier letters:
1588 A - address of a MEM
1589 S - SADDR form of a real register
1590 v - real register corresponding to a virtual register
1591 m - minus - negative of CONST_INT value.
1592 C - inverse of a conditional (NE vs EQ for example)
1593 C - complement of an integer
1594 z - collapsed conditional
1595 s - shift count mod 8
1596 S - shift count mod 16
1597 r - reverse shift count (8-(count mod 8))
1600 h - bottom HI of an SI
1602 q - bottom QI of an HI
1604 e - third QI of an SI (i.e. where the ES register gets values from)
1605 E - fourth QI of an SI (i.e. MSB)
1607 p - Add +0 to a zero-indexed HL based address.
1610 /* Implements the bulk of rl78_print_operand, below. We do it this
1611 way because we need to test for a constant at the top level and
1612 insert the '#', but not test for it anywhere else as we recurse
1613 down into the operand. */
1615 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1619 switch (GET_CODE (op
))
1623 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1626 if (rl78_far_p (op
))
1628 fprintf (file
, "es:");
1629 if (GET_CODE (XEXP (op
, 0)) == UNSPEC
)
1630 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1634 op
= adjust_address (op
, HImode
, 2);
1639 op
= adjust_address (op
, HImode
, 0);
1644 op
= adjust_address (op
, QImode
, 1);
1649 op
= adjust_address (op
, QImode
, 0);
1654 op
= adjust_address (op
, QImode
, 2);
1659 op
= adjust_address (op
, QImode
, 3);
1662 if (CONSTANT_P (XEXP (op
, 0)))
1664 if (!rl78_saddr_p (op
))
1665 fprintf (file
, "!");
1666 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1668 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1669 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1671 if (!rl78_saddr_p (op
))
1672 fprintf (file
, "!");
1673 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1675 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1676 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1677 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1679 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1680 fprintf (file
, "[");
1681 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1682 if (letter
== 'p' && GET_CODE (XEXP (op
, 0)) == REG
)
1683 fprintf (file
, "+0");
1684 fprintf (file
, "]");
1689 fprintf (file
, "[");
1690 rl78_print_operand_1 (file
, op
, letter
);
1691 if (letter
== 'p' && REG_P (op
) && REGNO (op
) == 6)
1692 fprintf (file
, "+0");
1693 fprintf (file
, "]");
1700 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1701 else if (letter
== 'H')
1702 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1703 else if (letter
== 'q')
1704 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1705 else if (letter
== 'e')
1706 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1707 else if (letter
== 'E')
1708 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1709 else if (letter
== 'S')
1710 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1711 else if (GET_MODE (op
) == HImode
1712 && ! (REGNO (op
) & ~0xfe))
1715 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1717 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1720 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1725 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1726 else if (letter
== 'H')
1727 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1728 else if (letter
== 'q')
1729 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1730 else if (letter
== 'h')
1731 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1732 else if (letter
== 'e')
1733 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1734 else if (letter
== 'B')
1736 int ival
= INTVAL (op
);
1739 if (exact_log2 (ival
) >= 0)
1740 fprintf (file
, "%d", exact_log2 (ival
));
1742 fprintf (file
, "%d", exact_log2 (~ival
& 0xff));
1744 else if (letter
== 'E')
1745 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1746 else if (letter
== 'm')
1747 fprintf (file
, "%ld", - INTVAL (op
));
1748 else if (letter
== 's')
1749 fprintf (file
, "%ld", INTVAL (op
) % 8);
1750 else if (letter
== 'S')
1751 fprintf (file
, "%ld", INTVAL (op
) % 16);
1752 else if (letter
== 'r')
1753 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1754 else if (letter
== 'C')
1755 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1757 fprintf (file
, "%ld", INTVAL (op
));
1761 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1766 int bits
= INTVAL (XEXP (op
, 1));
1767 int ofs
= INTVAL (XEXP (op
, 2));
1768 if (bits
== 16 && ofs
== 0)
1769 fprintf (file
, "%%lo16(");
1770 else if (bits
== 16 && ofs
== 16)
1771 fprintf (file
, "%%hi16(");
1772 else if (bits
== 8 && ofs
== 16)
1773 fprintf (file
, "%%hi8(");
1776 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1777 fprintf (file
, ")");
1782 if (GET_CODE (XEXP (op
, 0)) == REG
)
1783 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1785 print_rtl (file
, op
);
1792 fprintf (file
, "%%hi16(");
1798 fprintf (file
, "%%lo16(");
1804 fprintf (file
, "%%hi8(");
1808 if (letter
== 'q' || letter
== 'Q')
1809 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1811 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1813 if (GET_CODE (XEXP (op
, 1)) == SYMBOL_REF
1814 && SYMBOL_REF_DECL (XEXP (op
, 1))
1815 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 1))) == FUNCTION_DECL
)
1817 fprintf (file
, "%%code(");
1818 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 1), 0)));
1819 fprintf (file
, "+");
1820 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1821 fprintf (file
, ")");
1825 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1826 fprintf (file
, "+");
1827 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1832 if (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1833 && SYMBOL_REF_DECL (XEXP (op
, 0))
1834 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 0))) == FUNCTION_DECL
)
1836 fprintf (file
, "%%code(");
1837 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 0), 0)));
1838 fprintf (file
, "+");
1839 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1840 fprintf (file
, ")");
1844 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1845 fprintf (file
, "+");
1846 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1850 fprintf (file
, ")");
1854 if (GET_MODE (op
) == HImode
1855 && SUBREG_BYTE (op
) == 0)
1857 fprintf (file
, "%%lo16(");
1858 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1859 fprintf (file
, ")");
1861 else if (GET_MODE (op
) == HImode
1862 && SUBREG_BYTE (op
) == 2)
1864 fprintf (file
, "%%hi16(");
1865 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1866 fprintf (file
, ")");
1870 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1878 fprintf (file
, "%%hi16(");
1884 fprintf (file
, "%%lo16(");
1890 fprintf (file
, "%%hi8(");
1894 if (letter
== 'q' || letter
== 'Q')
1895 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1897 if (SYMBOL_REF_DECL (op
) && TREE_CODE (SYMBOL_REF_DECL (op
)) == FUNCTION_DECL
)
1899 fprintf (file
, "%%code(");
1900 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
1901 fprintf (file
, ")");
1904 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
1906 fprintf (file
, ")");
1911 output_asm_label (op
);
1916 fprintf (file
, "#comparison eliminated");
1918 fprintf (file
, letter
== 'C' ? "nc" : "c");
1922 fprintf (file
, "br");
1924 fprintf (file
, letter
== 'C' ? "h" : "nh");
1928 fprintf (file
, "br");
1930 fprintf (file
, letter
== 'C' ? "c" : "nc");
1934 fprintf (file
, "#comparison eliminated");
1936 fprintf (file
, letter
== 'C' ? "nh" : "h");
1940 fprintf (file
, "br");
1942 fprintf (file
, letter
== 'C' ? "nz" : "z");
1946 fprintf (file
, "#comparison eliminated");
1948 fprintf (file
, letter
== 'C' ? "z" : "nz");
1951 /* Note: these assume appropriate adjustments were made so that
1952 unsigned comparisons, which is all this chip has, will
1956 fprintf (file
, "#comparison eliminated");
1958 fprintf (file
, letter
== 'C' ? "nc" : "c");
1962 fprintf (file
, "br");
1964 fprintf (file
, letter
== 'C' ? "h" : "nh");
1968 fprintf (file
, "br");
1970 fprintf (file
, letter
== 'C' ? "c" : "nc");
1974 fprintf (file
, "#comparison eliminated");
1976 fprintf (file
, letter
== 'C' ? "nh" : "h");
1980 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1985 #undef TARGET_PRINT_OPERAND
1986 #define TARGET_PRINT_OPERAND rl78_print_operand
1989 rl78_print_operand (FILE * file
, rtx op
, int letter
)
1991 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
1992 fprintf (file
, "#");
1993 rl78_print_operand_1 (file
, op
, letter
);
1996 #undef TARGET_TRAMPOLINE_INIT
1997 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
1999 /* Note that the RL78's addressing makes it very difficult to do
2000 trampolines on the stack. So, libgcc has a small pool of
2001 trampolines from which one is allocated to this task. */
2003 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2005 rtx mov_addr
, thunk_addr
;
2006 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
2008 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
2009 thunk_addr
= gen_reg_rtx (HImode
);
2011 function
= force_reg (HImode
, function
);
2012 static_chain
= force_reg (HImode
, static_chain
);
2014 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
2015 emit_move_insn (mov_addr
, thunk_addr
);
2017 cfun
->machine
->trampolines_used
= 1;
2020 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2021 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2024 rl78_trampoline_adjust_address (rtx m_tramp
)
2026 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
2030 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2031 the "normal" compares, specifically, it only has unsigned compares,
2032 so we must synthesize the missing ones. */
2034 rl78_expand_compare (rtx
*operands
)
2036 if (GET_CODE (operands
[2]) == MEM
)
2037 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
2042 /* Define this to 1 if you are debugging the peephole optimizers. */
2043 #define DEBUG_PEEP 0
2045 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2046 The default "word" size is a byte so we can effectively use all the
2047 registers, but we want to do 16-bit moves whenever possible. This
2048 function determines when such a move is an option. */
2050 rl78_peep_movhi_p (rtx
*operands
)
2055 /* (set (op0) (op1))
2056 (set (op2) (op3)) */
2058 if (! rl78_virt_insns_ok ())
2062 fprintf (stderr
, "\033[33m");
2063 debug_rtx (operands
[0]);
2064 debug_rtx (operands
[1]);
2065 debug_rtx (operands
[2]);
2066 debug_rtx (operands
[3]);
2067 fprintf (stderr
, "\033[0m");
2070 /* You can move a constant to memory as QImode, but not HImode. */
2071 if (GET_CODE (operands
[0]) == MEM
2072 && GET_CODE (operands
[1]) != REG
)
2075 fprintf (stderr
, "no peep: move constant to memory\n");
2080 if (rtx_equal_p (operands
[0], operands
[3]))
2083 fprintf (stderr
, "no peep: overlapping\n");
2088 for (i
= 0; i
< 2; i
++)
2090 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
2093 fprintf (stderr
, "no peep: different codes\n");
2097 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
2100 fprintf (stderr
, "no peep: different modes\n");
2105 switch (GET_CODE (operands
[i
]))
2109 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
2110 || GET_MODE (operands
[i
]) != QImode
)
2113 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
2114 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
2119 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
2122 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
2132 if (GET_MODE (operands
[i
]) != QImode
)
2134 if (MEM_ALIGN (operands
[i
]) < 16)
2136 a
= XEXP (operands
[i
], 0);
2137 if (GET_CODE (a
) == CONST
)
2139 if (GET_CODE (a
) == PLUS
)
2141 if (GET_CODE (a
) == CONST_INT
2145 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
2146 debug_rtx (operands
[i
]);
2150 m
= adjust_address (operands
[i
], QImode
, 1);
2151 if (! rtx_equal_p (m
, operands
[i
+2]))
2154 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
2156 debug_rtx (operands
[i
+2]);
2164 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
2170 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
2175 /* Likewise, when a peephole is activated, this function helps compute
2176 the new operands. */
2178 rl78_setup_peep_movhi (rtx
*operands
)
2182 for (i
= 0; i
< 2; i
++)
2184 switch (GET_CODE (operands
[i
]))
2187 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
2191 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char) INTVAL (operands
[i
+2])) * 256);
2195 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
2205 How Devirtualization works in the RL78 GCC port
2209 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2210 bytes of register space, in four banks, memory-mapped. One bank is
2211 the "selected" bank and holds the registers used for primary
2212 operations. Since the registers are memory mapped, often you can
2213 still refer to the unselected banks via memory accesses.
2217 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2218 and refers to the other banks via their memory addresses, although
2219 they're treated as regular registers internally. These "virtual"
2220 registers are R8 through R23 (bank3 is reserved for asm-based
2221 interrupt handlers).
2223 There are four machine description files:
2225 rl78.md - common register-independent patterns and definitions
2226 rl78-expand.md - expanders
2227 rl78-virt.md - patterns that match BEFORE devirtualization
2228 rl78-real.md - patterns that match AFTER devirtualization
2230 At least through register allocation and reload, gcc is told that it
2231 can do pretty much anything - but may only use the virtual registers.
2232 GCC cannot properly create the varying addressing modes that the RL78
2233 supports in an efficient way.
2235 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2236 uses the "valloc" attribute in rl78-virt.md for determining the rules
2237 by which it will replace virtual registers with real registers (or
2238 not) and how to make up addressing modes. For example, insns tagged
2239 with "ro1" have a single read-only parameter, which may need to be
2240 moved from memory/constant/vreg to a suitable real register. As part
2241 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2242 patterns and enabling the rl78-real.md patterns. The new patterns'
2243 constraints are used to determine the real registers used. NOTE:
2244 patterns in rl78-virt.md essentially ignore the constrains and rely on
2245 predicates, where the rl78-real.md ones essentially ignore the
2246 predicates and rely on the constraints.
2248 The devirtualization pass is scheduled via the pass manager (despite
2249 being called "rl78_reorg") so it can be scheduled prior to var-track
2250 (the idea is to let gdb know about the new registers). Ideally, it
2251 would be scheduled right after pro/epilogue generation, so the
2252 post-reload optimizers could operate on the real registers, but when I
2253 tried that there were some issues building the target libraries.
2255 During devirtualization, a simple register move optimizer is run. It
2256 would be better to run a full CSE/propogation pass on it though, but
2257 that has not yet been attempted.
2260 #define DEBUG_ALLOC 0
2262 #define OP(x) (*recog_data.operand_loc[x])
2264 /* This array is used to hold knowledge about the contents of the
2265 real registers (A ... H), the memory-based registers (r8 ... r31)
2266 and the first NUM_STACK_LOCS words on the stack. We use this to
2267 avoid generating redundant move instructions.
2269 A value in the range 0 .. 31 indicates register A .. r31.
2270 A value in the range 32 .. 63 indicates stack slot (value - 32).
2271 A value of NOT_KNOWN indicates that the contents of that location
2274 #define NUM_STACK_LOCS 32
2275 #define NOT_KNOWN 127
2277 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
2279 static unsigned char saved_update_index
= NOT_KNOWN
;
2280 static unsigned char saved_update_value
;
2281 static machine_mode saved_update_mode
;
2285 clear_content_memory (void)
2287 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
2289 fprintf (dump_file
, " clear content memory\n");
2290 saved_update_index
= NOT_KNOWN
;
2293 /* Convert LOC into an index into the content_memory array.
2294 If LOC cannot be converted, return NOT_KNOWN. */
2296 static unsigned char
2297 get_content_index (rtx loc
)
2301 if (loc
== NULL_RTX
)
2306 if (REGNO (loc
) < 32)
2311 mode
= GET_MODE (loc
);
2313 if (! rl78_stack_based_mem (loc
, mode
))
2316 loc
= XEXP (loc
, 0);
2319 /* loc = MEM (SP) */
2322 /* loc = MEM (PLUS (SP, INT)). */
2323 loc
= XEXP (loc
, 1);
2325 if (INTVAL (loc
) < NUM_STACK_LOCS
)
2326 return 32 + INTVAL (loc
);
2331 /* Return a string describing content INDEX in mode MODE.
2332 WARNING: Can return a pointer to a static buffer. */
2334 get_content_name (unsigned char index
, machine_mode mode
)
2336 static char buffer
[128];
2338 if (index
== NOT_KNOWN
)
2342 sprintf (buffer
, "stack slot %d", index
- 32);
2343 else if (mode
== HImode
)
2344 sprintf (buffer
, "%s%s",
2345 reg_names
[index
+ 1], reg_names
[index
]);
2347 return reg_names
[index
];
2355 display_content_memory (FILE * file
)
2359 fprintf (file
, " Known memory contents:\n");
2361 for (i
= 0; i
< sizeof content_memory
; i
++)
2362 if (content_memory
[i
] != NOT_KNOWN
)
2364 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
2365 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2371 update_content (unsigned char index
, unsigned char val
, machine_mode mode
)
2375 gcc_assert (index
< sizeof content_memory
);
2377 content_memory
[index
] = val
;
2378 if (val
!= NOT_KNOWN
)
2379 content_memory
[val
] = index
;
2381 /* Make the entry in dump_file *before* VAL is increased below. */
2384 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2385 if (val
== NOT_KNOWN
)
2386 fprintf (dump_file
, "Unknown\n");
2388 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2393 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2395 content_memory
[index
+ 1] = val
;
2396 if (val
!= NOT_KNOWN
)
2398 content_memory
[val
] = index
+ 1;
2403 /* Any other places that had INDEX recorded as their contents are now invalid. */
2404 for (i
= 0; i
< sizeof content_memory
; i
++)
2407 || (val
!= NOT_KNOWN
&& i
== val
))
2414 if (content_memory
[i
] == index
2415 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2417 content_memory
[i
] = NOT_KNOWN
;
2420 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2423 content_memory
[++ i
] = NOT_KNOWN
;
2428 /* Record that LOC contains VALUE.
2429 For HImode locations record that LOC+1 contains VALUE+1.
2430 If LOC is not a register or stack slot, do nothing.
2431 If VALUE is not a register or stack slot, clear the recorded content. */
2434 record_content (rtx loc
, rtx value
)
2437 unsigned char index
;
2440 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2443 val
= get_content_index (value
);
2445 mode
= GET_MODE (loc
);
2452 /* This should not happen when optimizing. */
2454 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2455 get_content_name (val
, mode
));
2462 update_content (index
, val
, mode
);
2465 /* Returns TRUE if LOC already contains a copy of VALUE. */
2468 already_contains (rtx loc
, rtx value
)
2470 unsigned char index
;
2473 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2476 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2479 if (content_memory
[index
] != val
)
2482 if (GET_MODE (loc
) == HImode
)
2483 return content_memory
[index
+ 1] == val
+ 1;
2489 rl78_es_addr (rtx addr
)
2491 if (GET_CODE (addr
) == MEM
)
2492 addr
= XEXP (addr
, 0);
2493 if (GET_CODE (addr
) != UNSPEC
)
2495 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2501 rl78_es_base (rtx addr
)
2503 if (GET_CODE (addr
) == MEM
)
2504 addr
= XEXP (addr
, 0);
2505 addr
= XVECEXP (addr
, 0, 1);
2506 if (GET_CODE (addr
) == CONST
2507 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2508 addr
= XEXP (XEXP (addr
, 0), 0);
2509 /* Mode doesn't matter here. */
2510 return gen_rtx_MEM (HImode
, addr
);
2513 /* Rescans an insn to see if it's recognized again. This is done
2514 carefully to ensure that all the constraint information is accurate
2515 for the newly matched insn. */
2517 insn_ok_now (rtx_insn
* insn
)
2519 rtx pattern
= PATTERN (insn
);
2522 INSN_CODE (insn
) = -1;
2524 if (recog (pattern
, insn
, 0) > -1)
2526 extract_insn (insn
);
2527 if (constrain_operands (1, get_preferred_alternatives (insn
)))
2530 fprintf (stderr
, "\033[32m");
2532 fprintf (stderr
, "\033[0m");
2534 if (SET_P (pattern
))
2535 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2537 /* We need to detect far addresses that haven't been
2538 converted to es/lo16 format. */
2539 for (i
=0; i
<recog_data
.n_operands
; i
++)
2540 if (GET_CODE (OP (i
)) == MEM
2541 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2542 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2550 /* We need to re-recog the insn with virtual registers to get
2552 cfun
->machine
->virt_insns_ok
= 1;
2553 if (recog (pattern
, insn
, 0) > -1)
2555 extract_insn (insn
);
2556 if (constrain_operands (0, get_preferred_alternatives (insn
)))
2558 cfun
->machine
->virt_insns_ok
= 0;
2564 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2571 fprintf (stderr
, "\033[31m");
2573 fprintf (stderr
, "\033[0m");
2579 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2580 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2581 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2582 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2583 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2585 #define FAILED gcc_unreachable ()
2586 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2587 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2590 /* Registers into which we move the contents of virtual registers. */
2591 #define X gen_rtx_REG (QImode, X_REG)
2592 #define A gen_rtx_REG (QImode, A_REG)
2593 #define C gen_rtx_REG (QImode, C_REG)
2594 #define B gen_rtx_REG (QImode, B_REG)
2595 #define E gen_rtx_REG (QImode, E_REG)
2596 #define D gen_rtx_REG (QImode, D_REG)
2597 #define L gen_rtx_REG (QImode, L_REG)
2598 #define H gen_rtx_REG (QImode, H_REG)
2600 #define AX gen_rtx_REG (HImode, AX_REG)
2601 #define BC gen_rtx_REG (HImode, BC_REG)
2602 #define DE gen_rtx_REG (HImode, DE_REG)
2603 #define HL gen_rtx_REG (HImode, HL_REG)
2605 /* Returns TRUE if R is a virtual register. */
2607 is_virtual_register (rtx r
)
2609 return (GET_CODE (r
) == REG
2614 /* In all these alloc routines, we expect the following: the insn
2615 pattern is unshared, the insn was previously recognized and failed
2616 due to predicates or constraints, and the operand data is in
2619 static int virt_insn_was_frame
;
2621 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2624 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2627 fprintf (stderr
, "\033[36m%d: ", line
);
2629 fprintf (stderr
, "\033[0m");
2631 /*SCHED_GROUP_P (r) = 1;*/
2632 if (virt_insn_was_frame
)
2633 RTX_FRAME_RELATED_P (r
) = 1;
2637 #define EM(x) EM2 (__LINE__, x)
2639 /* Return a suitable RTX for the low half of a __far address. */
2641 rl78_lo16 (rtx addr
)
2645 if (GET_CODE (addr
) == SYMBOL_REF
2646 || GET_CODE (addr
) == CONST
)
2648 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2649 r
= gen_rtx_CONST (HImode
, r
);
2652 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2654 r
= gen_es_addr (r
);
2655 cfun
->machine
->uses_es
= true;
2660 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2664 if (GET_CODE (addr
) == SYMBOL_REF
2665 || GET_CODE (addr
) == CONST
)
2667 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2668 r
= gen_rtx_CONST (QImode
, r
);
2671 return rl78_subreg (QImode
, addr
, SImode
, 2);
2675 add_postponed_content_update (rtx to
, rtx value
)
2677 unsigned char index
;
2679 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2682 gcc_assert (saved_update_index
== NOT_KNOWN
);
2683 saved_update_index
= index
;
2684 saved_update_value
= get_content_index (value
);
2685 saved_update_mode
= GET_MODE (to
);
2689 process_postponed_content_update (void)
2691 if (saved_update_index
!= NOT_KNOWN
)
2693 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2694 saved_update_index
= NOT_KNOWN
;
2698 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2699 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2700 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2701 BEFORE is true, FROM otherwise. */
2703 gen_and_emit_move (rtx to
, rtx from
, rtx where
, bool before
)
2705 machine_mode mode
= GET_MODE (to
);
2707 if (optimize
&& before
&& already_contains (to
, from
))
2710 display_content_memory (stderr
);
2714 fprintf (dump_file
, " Omit move of %s into ",
2715 get_content_name (get_content_index (from
), mode
));
2716 fprintf (dump_file
, "%s as it already contains this value\n",
2717 get_content_name (get_content_index (to
), mode
));
2722 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2726 if (where
== NULL_RTX
)
2729 emit_insn_before (move
, where
);
2732 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2734 /* If necessary move REG_EH_REGION notes forward.
2735 cf. compiling gcc.dg/pr44545.c. */
2736 if (note
!= NULL_RTX
)
2738 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2739 remove_note (where
, note
);
2742 emit_insn_after (move
, where
);
2746 record_content (to
, from
);
2748 add_postponed_content_update (to
, from
);
2751 return before
? to
: from
;
2754 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2755 copy it into NEWBASE and return the updated MEM. Otherwise just
2756 return M. Any needed insns are emitted before BEFORE. */
2758 transcode_memory_rtx (rtx m
, rtx newbase
, rtx before
)
2760 rtx base
, index
, addendr
;
2767 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2770 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2774 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2775 emit_insn_before (EM (gen_movqi_to_es (A
)), before
);
2778 record_content (A
, NULL_RTX
);
2780 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2781 MEM_COPY_ATTRIBUTES (new_m
, m
);
2786 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2787 gcc_assert (index
== NULL_RTX
);
2789 if (base
== NULL_RTX
)
2792 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2793 addend
= INTVAL (addendr
);
2795 gcc_assert (REG_P (base
));
2796 gcc_assert (REG_P (newbase
));
2798 int limit
= 256 - GET_MODE_SIZE (GET_MODE (m
));
2800 if (REGNO (base
) == SP_REG
)
2802 if (addend
>= 0 && addend
<= limit
)
2806 /* BASE should be a virtual register. We copy it to NEWBASE. If
2807 the addend is out of range for DE/HL, we use AX to compute the full
2811 || (addend
> limit
&& REGNO (newbase
) != BC_REG
)
2813 && (GET_CODE (addendr
) != CONST_INT
)
2814 && ((REGNO (newbase
) != BC_REG
))
2820 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2821 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2822 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2823 record_content (AX
, NULL_RTX
);
2824 record_content (newbase
, NULL_RTX
);
2832 base
= gen_and_emit_move (newbase
, base
, before
, true);
2837 record_content (base
, NULL_RTX
);
2838 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2842 record_content (base
, NULL_RTX
);
2843 base
= gen_rtx_PLUS (HImode
, base
, addendr
);
2848 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2849 cfun
->machine
->uses_es
= true;
2852 m
= change_address (m
, GET_MODE (m
), base
);
2856 /* Copy SRC to accumulator (A or AX), placing any generated insns
2857 before BEFORE. Returns accumulator RTX. */
2859 move_to_acc (int opno
, rtx before
)
2861 rtx src
= OP (opno
);
2862 machine_mode mode
= GET_MODE (src
);
2864 if (REG_P (src
) && REGNO (src
) < 2)
2867 if (mode
== VOIDmode
)
2868 mode
= recog_data
.operand_mode
[opno
];
2870 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2874 force_into_acc (rtx src
, rtx before
)
2876 machine_mode mode
= GET_MODE (src
);
2879 if (REG_P (src
) && REGNO (src
) < 2)
2882 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2886 emit_insn_before (move
, before
);
2887 record_content (AX
, NULL_RTX
);
2890 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2891 after AFTER. Returns accumulator RTX. */
2893 move_from_acc (unsigned int opno
, rtx after
)
2895 rtx dest
= OP (opno
);
2896 machine_mode mode
= GET_MODE (dest
);
2898 if (REG_P (dest
) && REGNO (dest
) < 2)
2901 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
2904 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
2905 before BEFORE. Returns reg RTX. */
2907 move_acc_to_reg (rtx acc
, int regno
, rtx before
)
2909 machine_mode mode
= GET_MODE (acc
);
2912 reg
= gen_rtx_REG (mode
, regno
);
2914 return gen_and_emit_move (reg
, acc
, before
, true);
2917 /* Copy SRC to X, placing any generated insns before BEFORE.
2920 move_to_x (int opno
, rtx before
)
2922 rtx src
= OP (opno
);
2923 machine_mode mode
= GET_MODE (src
);
2926 if (mode
== VOIDmode
)
2927 mode
= recog_data
.operand_mode
[opno
];
2928 reg
= (mode
== QImode
) ? X
: AX
;
2930 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2932 OP (opno
) = move_to_acc (opno
, before
);
2933 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
2937 return gen_and_emit_move (reg
, src
, before
, true);
2940 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
2941 Returns H/HL RTX. */
2943 move_to_hl (int opno
, rtx before
)
2945 rtx src
= OP (opno
);
2946 machine_mode mode
= GET_MODE (src
);
2949 if (mode
== VOIDmode
)
2950 mode
= recog_data
.operand_mode
[opno
];
2951 reg
= (mode
== QImode
) ? L
: HL
;
2953 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2955 OP (opno
) = move_to_acc (opno
, before
);
2956 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
2960 return gen_and_emit_move (reg
, src
, before
, true);
2963 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
2964 Returns E/DE RTX. */
2966 move_to_de (int opno
, rtx before
)
2968 rtx src
= OP (opno
);
2969 machine_mode mode
= GET_MODE (src
);
2972 if (mode
== VOIDmode
)
2973 mode
= recog_data
.operand_mode
[opno
];
2975 reg
= (mode
== QImode
) ? E
: DE
;
2977 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
2979 OP (opno
) = move_to_acc (opno
, before
);
2980 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
2984 gen_and_emit_move (reg
, src
, before
, true);
2990 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
2992 rl78_alloc_physical_registers_op1 (rtx_insn
* insn
)
2994 /* op[0] = func op[1] */
2996 /* We first try using A as the destination, then copying it
2998 if (rtx_equal_p (OP (0), OP (1)))
3001 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3005 /* If necessary, load the operands into BC and HL.
3006 Check to see if we already have OP (0) in HL
3007 and if so, swap the order.
3009 It is tempting to perform this optimization when OP(0) does
3010 not hold a MEM, but this leads to bigger code in general.
3011 The problem is that if OP(1) holds a MEM then swapping it
3012 into BC means a BC-relative load is used and these are 3
3013 bytes long vs 1 byte for an HL load. */
3015 && already_contains (HL
, XEXP (OP (0), 0)))
3017 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
3018 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
3022 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3023 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3029 OP (0) = move_from_acc (0, insn
);
3033 /* Try copying the src to acc first, then. This is for, for
3034 example, ZERO_EXTEND or NOT. */
3035 OP (1) = move_to_acc (1, insn
);
3040 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3041 Assumes that the current insn has already been recognised and hence the
3042 constraint data has been filled in. */
3044 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
3046 const char * p
= recog_data
.constraints
[opnum
];
3048 /* No constraints means anything is accepted. */
3049 if (p
== NULL
|| *p
== 0 || *p
== ',')
3058 len
= CONSTRAINT_LEN (c
, p
);
3059 gcc_assert (len
> 0);
3067 if (lookup_constraint (p
) == constraint
)
3075 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3077 rl78_alloc_physical_registers_op2 (rtx_insn
* insn
)
3085 if (rtx_equal_p (OP (0), OP (1)))
3090 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3091 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3096 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3097 OP (2) = transcode_memory_rtx (OP (2), DE
, insn
);
3100 else if (rtx_equal_p (OP (0), OP (2)))
3102 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3104 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3108 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3109 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3110 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3115 prev
= prev_nonnote_nondebug_insn (insn
);
3116 if (recog_data
.constraints
[1][0] == '%'
3117 && is_virtual_register (OP (1))
3118 && ! is_virtual_register (OP (2))
3119 && ! CONSTANT_P (OP (2)))
3126 /* Make a note of whether (H)L is being used. It matters
3127 because if OP (2) also needs reloading, then we must take
3128 care not to corrupt HL. */
3129 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
3131 /* If HL is not currently being used and dest == op1 then there are
3132 some possible optimizations available by reloading one of the
3133 operands into HL, before trying to use the accumulator. */
3136 && rtx_equal_p (OP (0), OP (1)))
3138 /* If op0 is a Ws1 type memory address then switching the base
3139 address register to HL might allow us to perform an in-memory
3140 operation. (eg for the INCW instruction).
3142 FIXME: Adding the move into HL is costly if this optimization is not
3143 going to work, so for now, make sure that we know that the new insn will
3144 match the requirements of the addhi3_real pattern. Really we ought to
3145 generate a candidate sequence, test that, and then install it if the
3146 results are good. */
3147 if (satisfies_constraint_Ws1 (OP (0))
3148 && has_constraint (0, CONSTRAINT_Wh1
)
3149 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3151 rtx base
, index
, addend
, newbase
;
3153 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
3154 gcc_assert (index
== NULL_RTX
);
3155 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3157 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3158 if (addend
!= NULL_RTX
)
3160 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
3161 record_content (newbase
, NULL_RTX
);
3162 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
3164 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
3166 /* We do not want to fail here as this means that
3167 we have inserted useless insns into the stream. */
3171 else if (REG_P (OP (0))
3172 && satisfies_constraint_Ws1 (OP (2))
3173 && has_constraint (2, CONSTRAINT_Wh1
))
3175 rtx base
, index
, addend
, newbase
;
3177 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
3178 gcc_assert (index
== NULL_RTX
);
3179 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3181 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3182 if (addend
!= NULL_RTX
)
3184 gen_and_emit_move (HL
, base
, insn
, true);
3186 if (REGNO (OP (0)) != X_REG
)
3188 OP (1) = move_to_acc (1, insn
);
3189 OP (0) = move_from_acc (0, insn
);
3192 record_content (HL
, NULL_RTX
);
3193 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
3195 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
3197 /* We do not want to fail here as this means that
3198 we have inserted useless insns into the stream. */
3204 OP (0) = move_from_acc (0, insn
);
3206 tmp_id
= get_max_insn_count ();
3209 if (rtx_equal_p (OP (1), OP (2)))
3210 OP (2) = OP (1) = move_to_acc (1, insn
);
3212 OP (1) = move_to_acc (1, insn
);
3216 /* If we omitted the move of OP1 into the accumulator (because
3217 it was already there from a previous insn), then force the
3218 generation of the move instruction now. We know that we
3219 are about to emit a move into HL (or DE) via AX, and hence
3220 our optimization to remove the load of OP1 is no longer valid. */
3221 if (tmp_id
== get_max_insn_count ())
3222 force_into_acc (saved_op1
, insn
);
3224 /* We have to copy op2 to HL (or DE), but that involves AX, which
3225 already has a live value. Emit it before those insns. */
3228 first
= next_nonnote_nondebug_insn (prev
);
3230 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3233 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
3238 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3240 rl78_alloc_physical_registers_ro1 (rtx_insn
* insn
)
3242 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3246 OP (0) = move_to_acc (0, insn
);
3251 /* Devirtualize a compare insn. */
3253 rl78_alloc_physical_registers_cmp (rtx_insn
* insn
)
3257 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3260 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3261 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3263 /* HI compares have to have OP (1) in AX, but QI
3264 compares do not, so it is worth checking here. */
3267 /* For an HImode compare, OP (1) must always be in AX.
3268 But if OP (1) is a REG (and not AX), then we can avoid
3269 a reload of OP (1) if we reload OP (2) into AX and invert
3272 && REGNO (OP (1)) != AX_REG
3273 && GET_MODE (OP (1)) == HImode
3276 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
3278 OP (2) = move_to_acc (2, insn
);
3280 switch (GET_CODE (cmp
))
3285 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
3286 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
3287 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
3288 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
3301 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
3302 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
3304 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
3309 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3310 should be handled by the second alternative of the cbranchhi_real pattern. */
3311 if (rtx_equal_p (OP (1), OP (2)))
3313 OP (1) = OP (2) = BC
;
3317 tmp_id
= get_max_insn_count ();
3320 OP (1) = move_to_acc (1, insn
);
3324 /* If we omitted the move of OP1 into the accumulator (because
3325 it was already there from a previous insn), then force the
3326 generation of the move instruction now. We know that we
3327 are about to emit a move into HL via AX, and hence our
3328 optimization to remove the load of OP1 is no longer valid. */
3329 if (tmp_id
== get_max_insn_count ())
3330 force_into_acc (saved_op1
, insn
);
3332 /* We have to copy op2 to HL, but that involves the acc, which
3333 already has a live value. Emit it before those insns. */
3335 first
= next_nonnote_nondebug_insn (prev
);
3337 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3339 OP (2) = move_to_hl (2, first
);
3344 /* Like op2, but AX = A * X. */
3346 rl78_alloc_physical_registers_umul (rtx_insn
* insn
)
3348 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3353 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3354 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3355 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3359 if (recog_data
.constraints
[1][0] == '%'
3360 && is_virtual_register (OP (1))
3361 && !is_virtual_register (OP (2))
3362 && !CONSTANT_P (OP (2)))
3369 OP (0) = move_from_acc (0, insn
);
3371 tmp_id
= get_max_insn_count ();
3374 if (rtx_equal_p (OP (1), OP (2)))
3376 gcc_assert (GET_MODE (OP (2)) == QImode
);
3377 /* The MULU instruction does not support duplicate arguments
3378 but we know that if we copy OP (2) to X it will do so via
3379 A and thus OP (1) will already be loaded into A. */
3380 OP (2) = move_to_x (2, insn
);
3384 OP (1) = move_to_acc (1, insn
);
3388 /* If we omitted the move of OP1 into the accumulator (because
3389 it was already there from a previous insn), then force the
3390 generation of the move instruction now. We know that we
3391 are about to emit a move into HL (or DE) via AX, and hence
3392 our optimization to remove the load of OP1 is no longer valid. */
3393 if (tmp_id
== get_max_insn_count ())
3394 force_into_acc (saved_op1
, insn
);
3396 /* We have to copy op2 to X, but that involves the acc, which
3397 already has a live value. Emit it before those insns. */
3400 first
= next_nonnote_nondebug_insn (prev
);
3402 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3404 OP (2) = move_to_x (2, first
);
3410 rl78_alloc_address_registers_macax (rtx_insn
* insn
)
3413 bool replace_in_op0
= false;
3414 bool replace_in_op1
= false;
3418 /* Two different MEMs are not allowed. */
3420 for (op
= 2; op
>= 0; op
--)
3422 if (MEM_P (OP (op
)))
3424 if (op
== 0 && replace_in_op0
)
3426 if (op
== 1 && replace_in_op1
)
3432 /* If we replace a MEM, make sure that we replace it for all
3433 occurrences of the same MEM in the insn. */
3434 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3435 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3437 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3440 && ((GET_CODE (XEXP (OP (op
), 0)) == REG
3441 && REGNO (XEXP (OP (op
), 0)) == SP_REG
)
3442 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3443 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3445 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3446 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3454 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3457 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3468 rl78_alloc_address_registers_div (rtx_insn
* insn
)
3473 /* Scan all insns and devirtualize them. */
3475 rl78_alloc_physical_registers (void)
3477 /* During most of the compile, gcc is dealing with virtual
3478 registers. At this point, we need to assign physical registers
3479 to the vitual ones, and copy in/out as needed. */
3481 rtx_insn
*insn
, *curr
;
3482 enum attr_valloc valloc_method
;
3484 for (insn
= get_insns (); insn
; insn
= curr
)
3488 curr
= next_nonnote_nondebug_insn (insn
);
3491 && (GET_CODE (PATTERN (insn
)) == SET
3492 || GET_CODE (PATTERN (insn
)) == CALL
)
3493 && INSN_CODE (insn
) == -1)
3495 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3497 i
= recog (PATTERN (insn
), insn
, 0);
3503 INSN_CODE (insn
) = i
;
3507 cfun
->machine
->virt_insns_ok
= 0;
3508 cfun
->machine
->real_insns_ok
= 1;
3510 clear_content_memory ();
3512 for (insn
= get_insns (); insn
; insn
= curr
)
3516 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3521 clear_content_memory ();
3527 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3529 pattern
= PATTERN (insn
);
3530 if (GET_CODE (pattern
) == PARALLEL
)
3531 pattern
= XVECEXP (pattern
, 0, 0);
3532 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3533 clear_content_memory ();
3534 if (GET_CODE (pattern
) != SET
3535 && GET_CODE (pattern
) != CALL
)
3537 if (GET_CODE (pattern
) == SET
3538 && GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3541 valloc_method
= get_attr_valloc (insn
);
3543 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3545 if (valloc_method
== VALLOC_MACAX
)
3547 record_content (AX
, NULL_RTX
);
3548 record_content (BC
, NULL_RTX
);
3549 record_content (DE
, NULL_RTX
);
3551 else if (valloc_method
== VALLOC_DIVHI
)
3553 record_content (AX
, NULL_RTX
);
3554 record_content (BC
, NULL_RTX
);
3556 else if (valloc_method
== VALLOC_DIVSI
)
3558 record_content (AX
, NULL_RTX
);
3559 record_content (BC
, NULL_RTX
);
3560 record_content (DE
, NULL_RTX
);
3561 record_content (HL
, NULL_RTX
);
3564 if (insn_ok_now (insn
))
3567 INSN_CODE (insn
) = -1;
3569 if (RTX_FRAME_RELATED_P (insn
))
3570 virt_insn_was_frame
= 1;
3572 virt_insn_was_frame
= 0;
3574 switch (valloc_method
)
3577 rl78_alloc_physical_registers_op1 (insn
);
3580 rl78_alloc_physical_registers_op2 (insn
);
3583 rl78_alloc_physical_registers_ro1 (insn
);
3586 rl78_alloc_physical_registers_cmp (insn
);
3589 rl78_alloc_physical_registers_umul (insn
);
3590 record_content (AX
, NULL_RTX
);
3593 /* Macro that clobbers AX. */
3594 rl78_alloc_address_registers_macax (insn
);
3595 record_content (AX
, NULL_RTX
);
3596 record_content (BC
, NULL_RTX
);
3597 record_content (DE
, NULL_RTX
);
3600 rl78_alloc_address_registers_div (insn
);
3601 record_content (AX
, NULL_RTX
);
3602 record_content (BC
, NULL_RTX
);
3603 record_content (DE
, NULL_RTX
);
3604 record_content (HL
, NULL_RTX
);
3607 rl78_alloc_address_registers_div (insn
);
3608 record_content (AX
, NULL_RTX
);
3609 record_content (BC
, NULL_RTX
);
3615 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3616 clear_content_memory ();
3618 process_postponed_content_update ();
3622 fprintf (stderr
, "\033[0m");
3626 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3627 This function scans for uses of registers; the last use (i.e. first
3628 encounter when scanning backwards) triggers a REG_DEAD note if the
3629 reg was previously in DEAD[]. */
3631 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3640 code
= GET_CODE (s
);
3644 /* Compare registers by number. */
3649 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3650 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3651 print_rtl_single (dump_file
, s
);
3654 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3655 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3659 /* These codes have no constituent expressions
3670 /* These are kept unique for a given value. */
3677 fmt
= GET_RTX_FORMAT (code
);
3679 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3684 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3685 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3687 else if (fmt
[i
] == 'e')
3688 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3692 /* Like the previous function, but scan for SETs instead. */
3694 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3698 if (GET_CODE (d
) == MEM
)
3699 rl78_note_reg_uses (dead
, XEXP (d
, 0), insn
);
3701 if (GET_CODE (d
) != REG
)
3706 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3708 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3709 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3713 /* This is a rather crude register death pass. Death status is reset
3714 at every jump or call insn. */
3716 rl78_calculate_death_notes (void)
3718 char dead
[FIRST_PSEUDO_REGISTER
];
3722 memset (dead
, 0, sizeof (dead
));
3724 for (insn
= get_last_insn ();
3726 insn
= prev_nonnote_nondebug_insn (insn
))
3730 fprintf (dump_file
, "\n--------------------------------------------------");
3731 fprintf (dump_file
, "\nDead:");
3732 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3734 fprintf (dump_file
, " %s", reg_names
[i
]);
3735 fprintf (dump_file
, "\n");
3736 print_rtl_single (dump_file
, insn
);
3739 switch (GET_CODE (insn
))
3743 if (GET_CODE (p
) == PARALLEL
)
3745 rtx q
= XVECEXP (p
, 0 ,1);
3747 /* This happens with the DIV patterns. */
3748 if (GET_CODE (q
) == SET
)
3752 rl78_note_reg_set (dead
, d
, insn
);
3753 rl78_note_reg_uses (dead
, s
, insn
);
3756 p
= XVECEXP (p
, 0, 0);
3759 switch (GET_CODE (p
))
3764 rl78_note_reg_set (dead
, d
, insn
);
3765 rl78_note_reg_uses (dead
, s
, insn
);
3769 rl78_note_reg_uses (dead
, p
, insn
);
3778 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3780 memset (dead
, 1, sizeof (dead
));
3781 /* We expect a USE just prior to this, which will mark
3782 the actual return registers. The USE will have a
3783 death note, but we aren't going to be modifying it
3788 memset (dead
, 0, sizeof (dead
));
3795 print_rtl_single (dump_file
, insn
);
3799 /* Helper function to reset the origins in RP and the age in AGE for
3802 reset_origins (int *rp
, int *age
)
3805 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3813 set_origin (rtx pat
, rtx_insn
* insn
, int * origins
, int * age
)
3815 rtx src
= SET_SRC (pat
);
3816 rtx dest
= SET_DEST (pat
);
3817 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3820 if (GET_CODE (dest
) == REG
)
3822 int dr
= REGNO (dest
);
3824 if (GET_CODE (src
) == REG
)
3826 int sr
= REGNO (src
);
3828 int best_age
, best_reg
;
3830 /* See if the copy is not needed. */
3831 for (i
= 0; i
< mb
; i
++)
3832 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3838 fprintf (dump_file
, "deleting because dest already has correct value\n");
3843 if (dr
< 8 || sr
>= 8)
3850 /* See if the copy can be made from another
3851 bank 0 register instead, instead of the
3852 virtual src register. */
3853 for (ar
= 0; ar
< 8; ar
+= mb
)
3857 for (i
= 0; i
< mb
; i
++)
3858 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3861 /* The chip has some reg-reg move limitations. */
3862 if (mb
== 1 && dr
> 3)
3867 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3869 best_age
= age
[sr
+ i
];
3877 /* FIXME: copy debug info too. */
3878 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3883 for (i
= 0; i
< mb
; i
++)
3885 origins
[dr
+ i
] = origins
[sr
+ i
];
3886 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3891 /* The destination is computed, its origin is itself. */
3893 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3894 dr
, mb
, mb
== 1 ? "" : "s");
3896 for (i
= 0; i
< mb
; i
++)
3898 origins
[dr
+ i
] = dr
+ i
;
3903 /* Any registers marked with that reg as an origin are reset. */
3904 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3905 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
3912 /* Special case - our MUL patterns uses AX and sometimes BC. */
3913 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
3916 fprintf (dump_file
, "Resetting origin of AX/BC for MUL pattern.\n");
3918 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3919 if (i
<= 3 || origins
[i
] <= 3)
3925 else if (get_attr_valloc (insn
) == VALLOC_DIVHI
)
3928 fprintf (dump_file
, "Resetting origin of AX/DE for DIVHI pattern.\n");
3930 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3935 || origins
[i
] == A_REG
3936 || origins
[i
] == X_REG
3937 || origins
[i
] == D_REG
3938 || origins
[i
] == E_REG
)
3944 else if (get_attr_valloc (insn
) == VALLOC_DIVSI
)
3947 fprintf (dump_file
, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
3949 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3950 if (i
<= 7 || origins
[i
] <= 7)
3957 if (GET_CODE (src
) == ASHIFT
3958 || GET_CODE (src
) == ASHIFTRT
3959 || GET_CODE (src
) == LSHIFTRT
)
3961 rtx count
= XEXP (src
, 1);
3963 if (GET_CODE (count
) == REG
)
3965 /* Special case - our pattern clobbers the count register. */
3966 int r
= REGNO (count
);
3969 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
3971 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3972 if (i
== r
|| origins
[i
] == r
)
3981 /* The idea behind this optimization is to look for cases where we
3982 move data from A to B to C, and instead move from A to B, and A to
3983 C. If B is a virtual register or memory, this is a big win on its
3984 own. If B turns out to be unneeded after this, it's a bigger win.
3985 For each register, we try to determine where it's value originally
3986 came from, if it's propogated purely through moves (and not
3987 computes). The ORIGINS[] array has the regno for the "origin" of
3988 the value in the [regno] it's indexed by. */
3990 rl78_propogate_register_origins (void)
3992 int origins
[FIRST_PSEUDO_REGISTER
];
3993 int age
[FIRST_PSEUDO_REGISTER
];
3995 rtx_insn
*insn
, *ninsn
= NULL
;
3998 reset_origins (origins
, age
);
4000 for (insn
= get_insns (); insn
; insn
= ninsn
)
4002 ninsn
= next_nonnote_nondebug_insn (insn
);
4006 fprintf (dump_file
, "\n");
4007 fprintf (dump_file
, "Origins:");
4008 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4009 if (origins
[i
] != i
)
4010 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
4011 fprintf (dump_file
, "\n");
4012 print_rtl_single (dump_file
, insn
);
4015 switch (GET_CODE (insn
))
4021 reset_origins (origins
, age
);
4028 pat
= PATTERN (insn
);
4030 if (GET_CODE (pat
) == PARALLEL
)
4032 rtx clobber
= XVECEXP (pat
, 0, 1);
4033 pat
= XVECEXP (pat
, 0, 0);
4034 if (GET_CODE (clobber
) == CLOBBER
4035 && GET_CODE (XEXP (clobber
, 0)) == REG
)
4037 int cr
= REGNO (XEXP (clobber
, 0));
4038 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
4040 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
4041 for (i
= 0; i
< mb
; i
++)
4043 origins
[cr
+ i
] = cr
+ i
;
4047 /* This happens with the DIV patterns. */
4048 else if (GET_CODE (clobber
) == SET
)
4050 set_origin (clobber
, insn
, origins
, age
);
4056 if (GET_CODE (pat
) == SET
)
4058 set_origin (pat
, insn
, origins
, age
);
4060 else if (GET_CODE (pat
) == CLOBBER
4061 && GET_CODE (XEXP (pat
, 0)) == REG
)
4063 if (REG_P (XEXP (pat
, 0)))
4065 unsigned int reg
= REGNO (XEXP (pat
, 0));
4075 /* Remove any SETs where the destination is unneeded. */
4077 rl78_remove_unused_sets (void)
4079 rtx_insn
*insn
, *ninsn
= NULL
;
4082 for (insn
= get_insns (); insn
; insn
= ninsn
)
4084 ninsn
= next_nonnote_nondebug_insn (insn
);
4086 rtx set
= single_set (insn
);
4090 dest
= SET_DEST (set
);
4092 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
4095 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
4098 fprintf (dump_file
, "deleting because the set register is never used.\n");
4104 /* This is the top of the devritualization pass. */
4108 /* split2 only happens when optimizing, but we need all movSIs to be
4113 rl78_alloc_physical_registers ();
4117 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4118 print_rtl_with_bb (dump_file
, get_insns (), 0);
4121 rl78_propogate_register_origins ();
4122 rl78_calculate_death_notes ();
4126 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4127 print_rtl_with_bb (dump_file
, get_insns (), 0);
4128 fprintf (dump_file
, "\n======================================================================\n");
4131 rl78_remove_unused_sets ();
4133 /* The code after devirtualizing has changed so much that at this point
4134 we might as well just rescan everything. Note that
4135 df_rescan_all_insns is not going to help here because it does not
4136 touch the artificial uses and defs. */
4137 df_finish_pass (true);
4139 df_live_add_problem ();
4140 df_scan_alloc (NULL
);
4147 #undef TARGET_RETURN_IN_MEMORY
4148 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4151 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
4153 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
4154 return (size
== -1 || size
> 8);
4158 #undef TARGET_RTX_COSTS
4159 #define TARGET_RTX_COSTS rl78_rtx_costs
4162 rl78_rtx_costs (rtx x
,
4164 int outer_code ATTRIBUTE_UNUSED
,
4165 int opno ATTRIBUTE_UNUSED
,
4167 bool speed ATTRIBUTE_UNUSED
)
4169 if (code
== IF_THEN_ELSE
)
4171 *total
= COSTS_N_INSNS (10);
4175 if (GET_MODE (x
) == SImode
)
4181 *total
= COSTS_N_INSNS (14);
4182 else if (RL78_MUL_G13
)
4183 *total
= COSTS_N_INSNS (29);
4185 *total
= COSTS_N_INSNS (500);
4188 *total
= COSTS_N_INSNS (8);
4193 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4195 switch (INTVAL (XEXP (x
, 1)))
4197 case 0: *total
= COSTS_N_INSNS (0); break;
4198 case 1: *total
= COSTS_N_INSNS (6); break;
4199 case 2: case 3: case 4: case 5: case 6: case 7:
4200 *total
= COSTS_N_INSNS (10); break;
4201 case 8: *total
= COSTS_N_INSNS (6); break;
4202 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4203 *total
= COSTS_N_INSNS (10); break;
4204 case 16: *total
= COSTS_N_INSNS (3); break;
4205 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4206 *total
= COSTS_N_INSNS (4); break;
4207 case 24: *total
= COSTS_N_INSNS (4); break;
4208 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4209 *total
= COSTS_N_INSNS (5); break;
4213 *total
= COSTS_N_INSNS (10+4*16);
4221 static GTY(()) section
* saddr_section
;
4222 static GTY(()) section
* frodata_section
;
4225 rl78_saddr_p (rtx x
)
4231 if (GET_CODE (x
) == PLUS
)
4233 if (GET_CODE (x
) != SYMBOL_REF
)
4237 if (memcmp (c
, "@s.", 3) == 0)
4248 if (GET_CODE (x
) != CONST_INT
)
4251 if ((INTVAL (x
) & 0xFF00) != 0xFF00)
4257 #undef TARGET_STRIP_NAME_ENCODING
4258 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4261 rl78_strip_name_encoding (const char * sym
)
4267 else if (*sym
== '@' && sym
[2] == '.')
4274 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4275 is important if the stripped name is going to be passed to assemble_name()
4276 as that handles asterisk prefixed names in a special manner. */
4279 rl78_strip_nonasm_name_encoding (const char * sym
)
4283 if (*sym
== '@' && sym
[2] == '.')
4292 rl78_attrlist_to_encoding (tree list
, tree decl ATTRIBUTE_UNUSED
)
4296 if (is_attribute_p ("saddr", TREE_PURPOSE (list
)))
4298 list
= TREE_CHAIN (list
);
4304 #define RL78_ATTRIBUTES(decl) \
4305 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4306 : DECL_ATTRIBUTES (decl) \
4307 ? (DECL_ATTRIBUTES (decl)) \
4308 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4310 #undef TARGET_ENCODE_SECTION_INFO
4311 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4314 rl78_encode_section_info (tree decl
, rtx rtl
, int first
)
4317 const char * oldname
;
4322 tree rl78_attributes
;
4327 rtlname
= XEXP (rtl
, 0);
4329 if (GET_CODE (rtlname
) == SYMBOL_REF
)
4330 oldname
= XSTR (rtlname
, 0);
4331 else if (GET_CODE (rtlname
) == MEM
4332 && GET_CODE (XEXP (rtlname
, 0)) == SYMBOL_REF
)
4333 oldname
= XSTR (XEXP (rtlname
, 0), 0);
4337 type
= TREE_TYPE (decl
);
4338 if (type
== error_mark_node
)
4340 if (! DECL_P (decl
))
4342 rl78_attributes
= RL78_ATTRIBUTES (decl
);
4344 encoding
= rl78_attrlist_to_encoding (rl78_attributes
, decl
);
4348 newname
= (char *) alloca (strlen (oldname
) + 4);
4349 sprintf (newname
, "@%c.%s", encoding
, oldname
);
4350 idp
= get_identifier (newname
);
4352 gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (idp
));
4353 SYMBOL_REF_WEAK (XEXP (rtl
, 0)) = DECL_WEAK (decl
);
4354 SET_SYMBOL_REF_DECL (XEXP (rtl
, 0), decl
);
4358 #undef TARGET_ASM_INIT_SECTIONS
4359 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4362 rl78_asm_init_sections (void)
4365 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4366 "\t.section .saddr,\"aw\",@progbits");
4368 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4369 "\t.section .frodata,\"aw\",@progbits");
4372 #undef TARGET_ASM_SELECT_SECTION
4373 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4376 rl78_select_section (tree decl
,
4378 unsigned HOST_WIDE_INT align
)
4382 switch (TREE_CODE (decl
))
4385 if (!TREE_READONLY (decl
)
4386 || TREE_SIDE_EFFECTS (decl
)
4387 || !DECL_INITIAL (decl
)
4388 || (DECL_INITIAL (decl
) != error_mark_node
4389 && !TREE_CONSTANT (DECL_INITIAL (decl
))))
4393 if (! TREE_CONSTANT (decl
))
4401 if (TREE_CODE (decl
) == VAR_DECL
)
4403 const char *name
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
4405 if (name
[0] == '@' && name
[2] == '.')
4409 return saddr_section
;
4412 if (TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_FAR
4415 return frodata_section
;
4420 return TARGET_ES0
? frodata_section
: readonly_data_section
;
4422 switch (categorize_decl_for_section (decl
, reloc
))
4424 case SECCAT_TEXT
: return text_section
;
4425 case SECCAT_DATA
: return data_section
;
4426 case SECCAT_BSS
: return bss_section
;
4427 case SECCAT_RODATA
: return TARGET_ES0
? frodata_section
: readonly_data_section
;
4429 return default_select_section (decl
, reloc
, align
);
4434 rl78_output_labelref (FILE *file
, const char *str
)
4438 str2
= targetm
.strip_name_encoding (str
);
4440 fputs (user_label_prefix
, file
);
4445 rl78_output_aligned_common (FILE *stream
,
4446 tree decl ATTRIBUTE_UNUSED
,
4448 int size
, int align
, int global
)
4450 /* We intentionally don't use rl78_section_tag() here. */
4451 if (name
[0] == '@' && name
[2] == '.')
4453 const char *sec
= 0;
4457 switch_to_section (saddr_section
);
4466 while (align
> BITS_PER_UNIT
)
4471 name2
= targetm
.strip_name_encoding (name
);
4473 fprintf (stream
, "\t.global\t_%s\n", name2
);
4474 fprintf (stream
, "\t.p2align %d\n", p2align
);
4475 fprintf (stream
, "\t.type\t_%s,@object\n", name2
);
4476 fprintf (stream
, "\t.size\t_%s,%d\n", name2
, size
);
4477 fprintf (stream
, "_%s:\n\t.zero\t%d\n", name2
, size
);
4484 fprintf (stream
, "\t.local\t");
4485 assemble_name (stream
, name
);
4486 fprintf (stream
, "\n");
4488 fprintf (stream
, "\t.comm\t");
4489 assemble_name (stream
, name
);
4490 fprintf (stream
, ",%u,%u\n", size
, align
/ BITS_PER_UNIT
);
4493 #undef TARGET_INSERT_ATTRIBUTES
4494 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4497 rl78_insert_attributes (tree decl
, tree
*attributes ATTRIBUTE_UNUSED
)
4500 && TREE_CODE (decl
) == VAR_DECL
4501 && TREE_READONLY (decl
)
4502 && TREE_ADDRESSABLE (decl
)
4503 && TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_GENERIC
)
4505 tree type
= TREE_TYPE (decl
);
4506 tree attr
= TYPE_ATTRIBUTES (type
);
4507 int q
= TYPE_QUALS_NO_ADDR_SPACE (type
) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR
);
4509 TREE_TYPE (decl
) = build_type_attribute_qual_variant (type
, attr
, q
);
4513 #undef TARGET_ASM_INTEGER
4514 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4517 rl78_asm_out_integer (rtx x
, unsigned int size
, int aligned_p
)
4519 if (default_assemble_integer (x
, size
, aligned_p
))
4524 assemble_integer_with_op (".long\t", x
);
4531 #undef TARGET_UNWIND_WORD_MODE
4532 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4535 rl78_unwind_word_mode (void)
4540 #ifndef USE_COLLECT2
4541 #undef TARGET_ASM_CONSTRUCTOR
4542 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4543 #undef TARGET_ASM_DESTRUCTOR
4544 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4547 rl78_asm_ctor_dtor (rtx symbol
, int priority
, bool is_ctor
)
4551 if (priority
!= DEFAULT_INIT_PRIORITY
)
4553 /* This section of the function is based upon code copied
4554 from: gcc/varasm.c:get_cdtor_priority_section(). */
4557 sprintf (buf
, "%s.%.5u", is_ctor
? ".ctors" : ".dtors",
4558 MAX_INIT_PRIORITY
- priority
);
4559 sec
= get_section (buf
, 0, NULL
);
4562 sec
= is_ctor
? ctors_section
: dtors_section
;
4564 assemble_addr_to_section (symbol
, sec
);
4568 rl78_asm_constructor (rtx symbol
, int priority
)
4570 rl78_asm_ctor_dtor (symbol
, priority
, true);
4574 rl78_asm_destructor (rtx symbol
, int priority
)
4576 rl78_asm_ctor_dtor (symbol
, priority
, false);
4578 #endif /* ! USE_COLLECT2 */
4580 /* Scan backwards through the insn chain looking to see if the flags
4581 have been set for a comparison of OP against OPERAND. Start with
4582 the insn *before* the current insn. */
4585 rl78_flags_already_set (rtx op
, rtx operand
)
4587 /* We only track the Z flag. */
4588 if (GET_CODE (op
) != EQ
&& GET_CODE (op
) != NE
)
4591 /* This should not happen, but let's be paranoid. */
4592 if (current_output_insn
== NULL_RTX
)
4598 for (insn
= prev_nonnote_nondebug_insn (current_output_insn
);
4600 insn
= prev_nonnote_nondebug_insn (insn
))
4605 if (! INSN_P (insn
))
4608 /* Make sure that the insn can be recognized. */
4609 if (recog_memoized (insn
) == -1)
4612 enum attr_update_Z updated
= get_attr_update_Z (insn
);
4614 rtx set
= single_set (insn
);
4615 bool must_break
= (set
!= NULL_RTX
&& rtx_equal_p (operand
, SET_DEST (set
)));
4621 case UPDATE_Z_CLOBBER
:
4624 case UPDATE_Z_UPDATE_Z
:
4636 /* We have to re-recognize the current insn as the call(s) to
4637 get_attr_update_Z() above will have overwritten the recog_data cache. */
4638 recog_memoized (current_output_insn
);
4639 cleanup_subreg_operands (current_output_insn
);
4640 constrain_operands_cached (current_output_insn
, 1);
4645 #undef TARGET_PREFERRED_RELOAD_CLASS
4646 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4649 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t rclass
)
4651 if (rclass
== NO_REGS
)
4658 struct gcc_target targetm
= TARGET_INITIALIZER
;
4660 #include "gt-rl78.h"