1 /* Subroutines used for code generation on Renesas RL78 processors.
2 Copyright (C) 2011-2018 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/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
33 #include "stringpool.h"
38 #include "diagnostic-core.h"
40 #include "stor-layout.h"
43 #include "insn-attr.h"
48 #include "langhooks.h"
49 #include "tree-pass.h"
51 #include "tm-constrs.h" /* for satisfies_constraint_*(). */
54 /* This file should be included last. */
55 #include "target-def.h"
57 static inline bool is_interrupt_func (const_tree decl
);
58 static inline bool is_brk_interrupt_func (const_tree decl
);
59 static void rl78_reorg (void);
60 static const char *rl78_strip_name_encoding (const char *);
61 static const char *rl78_strip_nonasm_name_encoding (const char *);
62 static section
* rl78_select_section (tree
, int, unsigned HOST_WIDE_INT
);
65 /* Debugging statements are tagged with DEBUG0 only so that they can
66 be easily enabled individually, by replacing the '0' with '1' as
71 /* REGISTER_NAMES has the names for individual 8-bit registers, but
72 these have the names we need to use when referring to 16-bit
74 static const char * const word_regnames
[] =
76 "ax", "AX", "bc", "BC", "de", "DE", "hl", "HL",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
78 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
79 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
80 "sp", "ap", "psw", "es", "cs"
83 /* Structure for G13 MDUC registers. */
87 enum machine_mode mode
;
90 struct mduc_reg_type mduc_regs
[] =
100 struct GTY(()) machine_function
102 /* If set, the rest of the fields have been computed. */
104 /* Which register pairs need to be pushed in the prologue. */
105 int need_to_push
[FIRST_PSEUDO_REGISTER
/ 2];
107 /* These fields describe the frame layout... */
109 /* 4 bytes for saved PC */
112 int framesize_locals
;
113 int framesize_outgoing
;
117 /* If set, recog is allowed to match against the "real" patterns. */
119 /* If set, recog is allowed to match against the "virtual" patterns. */
121 /* Set if the current function needs to clean up any trampolines. */
122 int trampolines_used
;
123 /* True if the ES register is used and hence
124 needs to be saved inside interrupt handlers. */
128 /* This is our init_machine_status, as set in
129 rl78_option_override. */
130 static struct machine_function
*
131 rl78_init_machine_status (void)
133 struct machine_function
*m
;
135 m
= ggc_cleared_alloc
<machine_function
> ();
136 m
->virt_insns_ok
= 1;
141 /* This pass converts virtual instructions using virtual registers, to
142 real instructions using real registers. Rather than run it as
143 reorg, we reschedule it before vartrack to help with debugging. */
146 const pass_data pass_data_rl78_devirt
=
150 OPTGROUP_NONE
, /* optinfo_flags */
151 TV_MACH_DEP
, /* tv_id */
152 0, /* properties_required */
153 0, /* properties_provided */
154 0, /* properties_destroyed */
155 0, /* todo_flags_start */
156 0, /* todo_flags_finish */
159 class pass_rl78_devirt
: public rtl_opt_pass
162 pass_rl78_devirt (gcc::context
*ctxt
)
163 : rtl_opt_pass (pass_data_rl78_devirt
, ctxt
)
167 /* opt_pass methods: */
168 virtual unsigned int execute (function
*)
177 make_pass_rl78_devirt (gcc::context
*ctxt
)
179 return new pass_rl78_devirt (ctxt
);
182 /* Redundant move elimination pass. Must be run after the basic block
183 reordering pass for the best effect. */
186 move_elim_pass (void)
188 rtx_insn
*insn
, *ninsn
;
191 for (insn
= get_insns (); insn
; insn
= ninsn
)
195 ninsn
= next_nonnote_nondebug_insn (insn
);
197 if ((set
= single_set (insn
)) == NULL_RTX
)
203 /* If we have two SET insns in a row (without anything
204 between them) and the source of the second one is the
205 destination of the first one, and vice versa, then we
206 can eliminate the second SET. */
208 && rtx_equal_p (SET_DEST (prev
), SET_SRC (set
))
209 && rtx_equal_p (SET_DEST (set
), SET_SRC (prev
))
210 /* ... and none of the operands are volatile. */
211 && ! volatile_refs_p (SET_SRC (prev
))
212 && ! volatile_refs_p (SET_DEST (prev
))
213 && ! volatile_refs_p (SET_SRC (set
))
214 && ! volatile_refs_p (SET_DEST (set
)))
217 fprintf (dump_file
, " Delete insn %d because it is redundant\n",
228 print_rtl_with_bb (dump_file
, get_insns (), 0);
235 const pass_data pass_data_rl78_move_elim
=
238 "move_elim", /* name */
239 OPTGROUP_NONE
, /* optinfo_flags */
240 TV_MACH_DEP
, /* tv_id */
241 0, /* properties_required */
242 0, /* properties_provided */
243 0, /* properties_destroyed */
244 0, /* todo_flags_start */
245 0, /* todo_flags_finish */
248 class pass_rl78_move_elim
: public rtl_opt_pass
251 pass_rl78_move_elim (gcc::context
*ctxt
)
252 : rtl_opt_pass (pass_data_rl78_move_elim
, ctxt
)
256 /* opt_pass methods: */
257 virtual unsigned int execute (function
*) { return move_elim_pass (); }
262 make_pass_rl78_move_elim (gcc::context
*ctxt
)
264 return new pass_rl78_move_elim (ctxt
);
267 #undef TARGET_ASM_FILE_START
268 #define TARGET_ASM_FILE_START rl78_asm_file_start
271 rl78_asm_file_start (void)
277 /* The memory used is 0xffec8 to 0xffedf; real registers are in
278 0xffee0 to 0xffee7. */
279 for (i
= 8; i
< 32; i
++)
280 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", i
, 0xffec0 + i
);
284 for (i
= 0; i
< 8; i
++)
286 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 8 + i
, 0xffef0 + i
);
287 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 16 + i
, 0xffee8 + i
);
288 fprintf (asm_out_file
, "r%d\t=\t0x%x\n", 24 + i
, 0xffee0 + i
);
292 opt_pass
*rl78_devirt_pass
= make_pass_rl78_devirt (g
);
293 struct register_pass_info rl78_devirt_info
=
298 PASS_POS_INSERT_BEFORE
301 opt_pass
*rl78_move_elim_pass
= make_pass_rl78_move_elim (g
);
302 struct register_pass_info rl78_move_elim_info
=
307 PASS_POS_INSERT_AFTER
310 register_pass (& rl78_devirt_info
);
311 register_pass (& rl78_move_elim_info
);
315 rl78_output_symbol_ref (FILE * file
, rtx sym
)
317 tree type
= SYMBOL_REF_DECL (sym
);
318 const char *str
= XSTR (sym
, 0);
322 fputs (str
+ 1, file
);
326 str
= rl78_strip_nonasm_name_encoding (str
);
327 if (type
&& TREE_CODE (type
) == FUNCTION_DECL
)
329 fprintf (file
, "%%code(");
330 assemble_name (file
, str
);
334 assemble_name (file
, str
);
338 #undef TARGET_OPTION_OVERRIDE
339 #define TARGET_OPTION_OVERRIDE rl78_option_override
341 #define MUST_SAVE_MDUC_REGISTERS \
342 (TARGET_SAVE_MDUC_REGISTERS \
343 && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
346 rl78_option_override (void)
348 flag_omit_frame_pointer
= 1;
349 flag_no_function_cse
= 1;
350 flag_split_wide_types
= 0;
352 init_machine_status
= rl78_init_machine_status
;
358 for (i
= 24; i
< 32; i
++)
363 && strcmp (lang_hooks
.name
, "GNU C")
364 && strcmp (lang_hooks
.name
, "GNU C11")
365 && strcmp (lang_hooks
.name
, "GNU C17")
366 && strcmp (lang_hooks
.name
, "GNU C89")
367 && strcmp (lang_hooks
.name
, "GNU C99")
368 /* Compiling with -flto results in a language of GNU GIMPLE being used... */
369 && strcmp (lang_hooks
.name
, "GNU GIMPLE"))
370 /* Address spaces are currently only supported by C. */
371 error ("-mes0 can only be used with C");
373 if (TARGET_SAVE_MDUC_REGISTERS
&& !(TARGET_G13
|| RL78_MUL_G13
))
374 warning (0, "mduc registers only saved for G13 target");
376 switch (rl78_cpu_type
)
379 rl78_cpu_type
= CPU_G14
;
380 if (rl78_mul_type
== MUL_UNINIT
)
381 rl78_mul_type
= MUL_NONE
;
385 switch (rl78_mul_type
)
387 case MUL_UNINIT
: rl78_mul_type
= MUL_NONE
; break;
388 case MUL_NONE
: break;
389 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
390 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
395 switch (rl78_mul_type
)
397 case MUL_UNINIT
: rl78_mul_type
= MUL_G13
; break;
398 case MUL_NONE
: break;
400 /* The S2 core does not have mul/div instructions. */
401 case MUL_G14
: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
406 switch (rl78_mul_type
)
408 case MUL_UNINIT
: rl78_mul_type
= MUL_G14
; break;
409 case MUL_NONE
: break;
411 /* The G14 core does not have the hardware multiply peripheral used by the
412 G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
413 case MUL_G13
: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
419 /* Most registers are 8 bits. Some are 16 bits because, for example,
420 gcc doesn't like dealing with $FP as a register pair (the second
421 half of $fp is also 2 to keep reload happy wrt register pairs, but
422 no register class includes it). This table maps register numbers
424 static const int register_sizes
[] =
426 1, 1, 1, 1, 1, 1, 1, 1,
427 1, 1, 1, 1, 1, 1, 1, 1,
428 1, 1, 1, 1, 1, 1, 2, 2,
429 1, 1, 1, 1, 1, 1, 1, 1,
433 /* Predicates used in the MD patterns. This one is true when virtual
434 insns may be matched, which typically means before (or during) the
437 rl78_virt_insns_ok (void)
440 return cfun
->machine
->virt_insns_ok
;
444 /* Predicates used in the MD patterns. This one is true when real
445 insns may be matched, which typically means after (or during) the
448 rl78_real_insns_ok (void)
451 return cfun
->machine
->real_insns_ok
;
455 #undef TARGET_HARD_REGNO_NREGS
456 #define TARGET_HARD_REGNO_NREGS rl78_hard_regno_nregs
459 rl78_hard_regno_nregs (unsigned int regno
, machine_mode mode
)
461 int rs
= register_sizes
[regno
];
464 return ((GET_MODE_SIZE (mode
) + rs
- 1) / rs
);
467 #undef TARGET_HARD_REGNO_MODE_OK
468 #define TARGET_HARD_REGNO_MODE_OK rl78_hard_regno_mode_ok
471 rl78_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
473 int s
= GET_MODE_SIZE (mode
);
477 /* These are not to be used by gcc. */
478 if (regno
== 23 || regno
== ES_REG
|| regno
== CS_REG
)
480 /* $fp can always be accessed as a 16-bit value. */
481 if (regno
== FP_REG
&& s
== 2)
485 /* Since a reg-reg move is really a reg-mem move, we must
486 enforce alignment. */
487 if (s
> 1 && (regno
% 2))
492 return (mode
== BImode
);
493 /* All other registers must be accessed in their natural sizes. */
494 if (s
== register_sizes
[regno
])
499 #undef TARGET_MODES_TIEABLE_P
500 #define TARGET_MODES_TIEABLE_P rl78_modes_tieable_p
503 rl78_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
505 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
506 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
507 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
508 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
511 /* Simplify_gen_subreg() doesn't handle memory references the way we
512 need it to below, so we use this function for when we must get a
513 valid subreg in a "natural" state. */
515 rl78_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
517 if (GET_CODE (r
) == MEM
)
518 return adjust_address (r
, mode
, byte
);
520 return simplify_gen_subreg (mode
, r
, omode
, byte
);
523 /* Used by movsi. Split SImode moves into two HImode moves, using
524 appropriate patterns for the upper and lower halves of symbols. */
526 rl78_expand_movsi (rtx
*operands
)
528 rtx op00
, op02
, op10
, op12
;
530 op00
= rl78_subreg (HImode
, operands
[0], SImode
, 0);
531 op02
= rl78_subreg (HImode
, operands
[0], SImode
, 2);
532 if (GET_CODE (operands
[1]) == CONST
533 || GET_CODE (operands
[1]) == SYMBOL_REF
)
535 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
536 op10
= gen_rtx_CONST (HImode
, op10
);
537 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
538 op12
= gen_rtx_CONST (HImode
, op12
);
542 op10
= rl78_subreg (HImode
, operands
[1], SImode
, 0);
543 op12
= rl78_subreg (HImode
, operands
[1], SImode
, 2);
546 if (rtx_equal_p (operands
[0], operands
[1]))
548 else if (rtx_equal_p (op00
, op12
))
550 emit_move_insn (op02
, op12
);
551 emit_move_insn (op00
, op10
);
555 emit_move_insn (op00
, op10
);
556 emit_move_insn (op02
, op12
);
560 /* Generate code to move an SImode value. */
562 rl78_split_movsi (rtx
*operands
, machine_mode omode
)
564 rtx op00
, op02
, op10
, op12
;
566 op00
= rl78_subreg (HImode
, operands
[0], omode
, 0);
567 op02
= rl78_subreg (HImode
, operands
[0], omode
, 2);
569 if (GET_CODE (operands
[1]) == CONST
570 || GET_CODE (operands
[1]) == SYMBOL_REF
)
572 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
573 op10
= gen_rtx_CONST (HImode
, op10
);
574 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
575 op12
= gen_rtx_CONST (HImode
, op12
);
579 op10
= rl78_subreg (HImode
, operands
[1], omode
, 0);
580 op12
= rl78_subreg (HImode
, operands
[1], omode
, 2);
583 if (rtx_equal_p (operands
[0], operands
[1]))
585 else if (rtx_equal_p (op00
, op12
))
601 /* Used by various two-operand expanders which cannot accept all
602 operands in the "far" namespace. Force some such operands into
603 registers so that each pattern has at most one far operand. */
605 rl78_force_nonfar_2 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
))
610 /* FIXME: in the future, be smarter about only doing this if the
611 other operand is also far, assuming the devirtualizer can also
613 if (rl78_far_p (operands
[0]))
615 temp_reg
= operands
[0];
616 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
622 emit_insn (gen (operands
[0], operands
[1]));
624 emit_move_insn (temp_reg
, operands
[0]);
628 /* Likewise, but for three-operand expanders. */
630 rl78_force_nonfar_3 (rtx
*operands
, rtx (*gen
)(rtx
,rtx
,rtx
))
635 /* FIXME: Likewise. */
636 if (rl78_far_p (operands
[1]))
638 rtx temp_reg
= gen_reg_rtx (GET_MODE (operands
[1]));
639 emit_move_insn (temp_reg
, operands
[1]);
640 operands
[1] = temp_reg
;
643 if (rl78_far_p (operands
[0]))
645 temp_reg
= operands
[0];
646 operands
[0] = gen_reg_rtx (GET_MODE (operands
[0]));
652 emit_insn (gen (operands
[0], operands
[1], operands
[2]));
654 emit_move_insn (temp_reg
, operands
[0]);
659 rl78_one_far_p (rtx
*operands
, int n
)
664 for (i
= 0; i
< n
; i
++)
665 if (rl78_far_p (operands
[i
]))
669 else if (rtx_equal_p (operands
[i
], which
))
676 #undef TARGET_CAN_ELIMINATE
677 #define TARGET_CAN_ELIMINATE rl78_can_eliminate
680 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to ATTRIBUTE_UNUSED
)
685 /* Returns true if the given register needs to be saved by the
688 need_to_save (unsigned int regno
)
690 if (is_interrupt_func (cfun
->decl
))
692 /* We don't know what devirt will need */
696 /* We don't need to save registers that have
697 been reserved for interrupt handlers. */
701 /* If the handler is a non-leaf function then it may call
702 non-interrupt aware routines which will happily clobber
703 any call_used registers, so we have to preserve them.
704 We do not have to worry about the frame pointer register
705 though, as that is handled below. */
706 if (!crtl
->is_leaf
&& call_used_regs
[regno
] && regno
< 22)
709 /* Otherwise we only have to save a register, call_used
710 or not, if it is used by this handler. */
711 return df_regs_ever_live_p (regno
);
714 if (regno
== FRAME_POINTER_REGNUM
715 && (frame_pointer_needed
|| df_regs_ever_live_p (regno
)))
717 if (fixed_regs
[regno
])
719 if (crtl
->calls_eh_return
)
721 if (df_regs_ever_live_p (regno
)
722 && !call_used_regs
[regno
])
727 /* We use this to wrap all emitted insns in the prologue. */
731 RTX_FRAME_RELATED_P (x
) = 1;
735 /* Compute all the frame-related fields in our machine_function
738 rl78_compute_frame_info (void)
742 cfun
->machine
->computed
= 1;
743 cfun
->machine
->framesize_regs
= 0;
744 cfun
->machine
->framesize_locals
= get_frame_size ();
745 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
747 for (i
= 0; i
< 16; i
++)
748 if (need_to_save (i
* 2) || need_to_save (i
* 2 + 1))
750 cfun
->machine
->need_to_push
[i
] = 1;
751 cfun
->machine
->framesize_regs
+= 2;
754 cfun
->machine
->need_to_push
[i
] = 0;
756 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
757 cfun
->machine
->framesize_locals
++;
759 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
760 + cfun
->machine
->framesize_locals
761 + cfun
->machine
->framesize_outgoing
);
764 /* Returns true if the provided function has the specified attribute. */
766 has_func_attr (const_tree decl
, const char * func_attr
)
768 if (decl
== NULL_TREE
)
769 decl
= current_function_decl
;
771 return lookup_attribute (func_attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
774 /* Returns true if the provided function has the "interrupt" attribute. */
776 is_interrupt_func (const_tree decl
)
778 return has_func_attr (decl
, "interrupt") || has_func_attr (decl
, "brk_interrupt");
781 /* Returns true if the provided function has the "brk_interrupt" attribute. */
783 is_brk_interrupt_func (const_tree decl
)
785 return has_func_attr (decl
, "brk_interrupt");
788 /* Check "interrupt" attributes. */
790 rl78_handle_func_attribute (tree
* node
,
793 int flags ATTRIBUTE_UNUSED
,
796 gcc_assert (DECL_P (* node
));
797 gcc_assert (args
== NULL_TREE
);
799 if (TREE_CODE (* node
) != FUNCTION_DECL
)
801 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
803 * no_add_attrs
= true;
806 /* FIXME: We ought to check that the interrupt and exception
807 handler attributes have been applied to void functions. */
811 /* Check "naked" attributes. */
813 rl78_handle_naked_attribute (tree
* node
,
814 tree name ATTRIBUTE_UNUSED
,
816 int flags ATTRIBUTE_UNUSED
,
819 gcc_assert (DECL_P (* node
));
820 gcc_assert (args
== NULL_TREE
);
822 if (TREE_CODE (* node
) != FUNCTION_DECL
)
824 warning (OPT_Wattributes
, "naked attribute only applies to functions");
825 * no_add_attrs
= true;
828 /* Disable warnings about this function - eg reaching the end without
829 seeing a return statement - because the programmer is doing things
830 that gcc does not know about. */
831 TREE_NO_WARNING (* node
) = 1;
836 /* Check "saddr" attributes. */
838 rl78_handle_saddr_attribute (tree
* node
,
840 tree args ATTRIBUTE_UNUSED
,
841 int flags ATTRIBUTE_UNUSED
,
844 gcc_assert (DECL_P (* node
));
846 if (TREE_CODE (* node
) == FUNCTION_DECL
)
848 warning (OPT_Wattributes
, "%qE attribute doesn't apply to functions",
850 * no_add_attrs
= true;
856 #undef TARGET_ATTRIBUTE_TABLE
857 #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table
859 /* Table of RL78-specific attributes. */
860 const struct attribute_spec rl78_attribute_table
[] =
862 /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
863 affects_type_identity, handler, exclude. */
864 { "interrupt", 0, 0, true, false, false, false,
865 rl78_handle_func_attribute
, NULL
},
866 { "brk_interrupt", 0, 0, true, false, false, false,
867 rl78_handle_func_attribute
, NULL
},
868 { "naked", 0, 0, true, false, false, false,
869 rl78_handle_naked_attribute
, NULL
},
870 { "saddr", 0, 0, true, false, false, false,
871 rl78_handle_saddr_attribute
, NULL
},
872 { NULL
, 0, 0, false, false, false, false, NULL
, NULL
}
877 /* Break down an address RTX into its component base/index/addend
878 portions and return TRUE if the address is of a valid form, else
881 characterize_address (rtx x
, rtx
*base
, rtx
*index
, rtx
*addend
)
887 if (GET_CODE (x
) == UNSPEC
888 && XINT (x
, 1) == UNS_ES_ADDR
)
889 x
= XVECEXP (x
, 0, 1);
891 if (GET_CODE (x
) == REG
)
897 /* We sometimes get these without the CONST wrapper */
898 if (GET_CODE (x
) == PLUS
899 && GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
900 && GET_CODE (XEXP (x
, 1)) == CONST_INT
)
906 if (GET_CODE (x
) == PLUS
)
911 if (GET_CODE (*base
) == SUBREG
)
913 if (GET_MODE (*base
) == HImode
914 && GET_MODE (XEXP (*base
, 0)) == SImode
915 && GET_CODE (XEXP (*base
, 0)) == REG
)
917 /* This is a throw-away rtx just to tell everyone
918 else what effective register we're using. */
919 *base
= gen_rtx_REG (HImode
, REGNO (XEXP (*base
, 0)));
923 if (GET_CODE (*base
) != REG
924 && GET_CODE (x
) == REG
)
931 if (GET_CODE (*base
) != REG
)
934 if (GET_CODE (x
) == ZERO_EXTEND
935 && GET_CODE (XEXP (x
, 0)) == REG
)
937 *index
= XEXP (x
, 0);
942 switch (GET_CODE (x
))
945 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
946 && GET_CODE (XEXP (x
, 0)) == CONST_INT
)
957 switch (GET_CODE (XEXP (x
, 0)))
981 /* Used by the Whb constraint. Match addresses that use HL+B or HL+C
984 rl78_hl_b_c_addr_p (rtx op
)
988 if (GET_CODE (op
) != PLUS
)
992 if (GET_CODE (hl
) == ZERO_EXTEND
)
998 if (GET_CODE (hl
) != REG
)
1000 if (GET_CODE (bc
) != ZERO_EXTEND
)
1003 if (GET_CODE (bc
) != REG
)
1005 if (REGNO (hl
) != HL_REG
)
1007 if (REGNO (bc
) != B_REG
&& REGNO (bc
) != C_REG
)
1013 #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict)))
1015 /* Return the appropriate mode for a named address address. */
1017 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1018 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
1020 static scalar_int_mode
1021 rl78_addr_space_address_mode (addr_space_t addrspace
)
1025 case ADDR_SPACE_GENERIC
:
1027 case ADDR_SPACE_NEAR
:
1029 case ADDR_SPACE_FAR
:
1036 /* Used in various constraints and predicates to match operands in the
1037 "far" address space. */
1044 fprintf (stderr
, "\033[35mrl78_far_p: "); debug_rtx (x
);
1045 fprintf (stderr
, " = %d\033[0m\n", MEM_ADDR_SPACE (x
) == ADDR_SPACE_FAR
);
1048 /* Not all far addresses are legitimate, because the devirtualizer
1049 can't handle them. */
1050 if (! rl78_as_legitimate_address (GET_MODE (x
), XEXP (x
, 0), false, ADDR_SPACE_FAR
))
1053 return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x
))) == 32;
1056 /* Return the appropriate mode for a named address pointer. */
1057 #undef TARGET_ADDR_SPACE_POINTER_MODE
1058 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
1060 static scalar_int_mode
1061 rl78_addr_space_pointer_mode (addr_space_t addrspace
)
1065 case ADDR_SPACE_GENERIC
:
1067 case ADDR_SPACE_NEAR
:
1069 case ADDR_SPACE_FAR
:
1076 /* Returns TRUE for valid addresses. */
1077 #undef TARGET_VALID_POINTER_MODE
1078 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
1081 rl78_valid_pointer_mode (scalar_int_mode m
)
1083 return (m
== HImode
|| m
== SImode
);
1086 #undef TARGET_LEGITIMATE_CONSTANT_P
1087 #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant
1090 rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
)
1096 #define TARGET_LRA_P hook_bool_void_false
1098 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1099 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P rl78_as_legitimate_address
1102 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
,
1103 bool strict ATTRIBUTE_UNUSED
, addr_space_t as ATTRIBUTE_UNUSED
)
1105 rtx base
, index
, addend
;
1106 bool is_far_addr
= false;
1109 as_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (as
));
1111 if (GET_CODE (x
) == UNSPEC
1112 && XINT (x
, 1) == UNS_ES_ADDR
)
1114 x
= XVECEXP (x
, 0, 1);
1118 if (as_bits
== 16 && is_far_addr
)
1121 if (! characterize_address (x
, &base
, &index
, &addend
))
1124 /* We can't extract the high/low portions of a PLUS address
1125 involving a register during devirtualization, so make sure all
1126 such __far addresses do not have addends. This forces GCC to do
1127 the sum separately. */
1128 if (addend
&& base
&& as_bits
== 32 && GET_MODE (base
) == SImode
)
1133 int ir
= REGNO (index
);
1134 int br
= REGNO (base
);
1136 #define OK(test, debug) if (test) { /*fprintf(stderr, "%d: OK %s\n", __LINE__, debug);*/ return true; }
1137 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, B_REG
), "[hl+b]");
1138 OK (REG_IS (br
, HL_REG
) && REG_IS (ir
, C_REG
), "[hl+c]");
1142 if (strict
&& base
&& GET_CODE (base
) == REG
&& REGNO (base
) >= FIRST_PSEUDO_REGISTER
)
1145 if (! cfun
->machine
->virt_insns_ok
&& base
&& GET_CODE (base
) == REG
1146 && REGNO (base
) >= 8 && REGNO (base
) <= 31)
1152 /* Determine if one named address space is a subset of another. */
1153 #undef TARGET_ADDR_SPACE_SUBSET_P
1154 #define TARGET_ADDR_SPACE_SUBSET_P rl78_addr_space_subset_p
1157 rl78_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1162 subset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset
));
1163 superset_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset
));
1165 return (subset_bits
<= superset_bits
);
1168 #undef TARGET_ADDR_SPACE_CONVERT
1169 #define TARGET_ADDR_SPACE_CONVERT rl78_addr_space_convert
1171 /* Convert from one address space to another. */
1173 rl78_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1175 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1176 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1181 to_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as
));
1182 from_bits
= GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as
));
1184 if (to_bits
< from_bits
)
1187 /* This is unpredictable, as we're truncating off usable address
1190 warning (OPT_Waddress
, "converting far pointer to near pointer");
1191 result
= gen_reg_rtx (HImode
);
1192 if (GET_CODE (op
) == SYMBOL_REF
1193 || (GET_CODE (op
) == REG
&& REGNO (op
) >= FIRST_PSEUDO_REGISTER
))
1194 tmp
= gen_rtx_raw_SUBREG (HImode
, op
, 0);
1196 tmp
= simplify_subreg (HImode
, op
, SImode
, 0);
1197 gcc_assert (tmp
!= NULL_RTX
);
1198 emit_move_insn (result
, tmp
);
1201 else if (to_bits
> from_bits
)
1203 /* This always works. */
1204 result
= gen_reg_rtx (SImode
);
1205 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 0), op
);
1206 if (TREE_CODE (from_type
) == POINTER_TYPE
1207 && TREE_CODE (TREE_TYPE (from_type
)) == FUNCTION_TYPE
)
1208 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), const0_rtx
);
1210 emit_move_insn (rl78_subreg (HImode
, result
, SImode
, 2), GEN_INT (0x0f));
1218 /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */
1220 rl78_regno_mode_code_ok_for_base_p (int regno
, machine_mode mode ATTRIBUTE_UNUSED
,
1221 addr_space_t address_space ATTRIBUTE_UNUSED
,
1222 int outer_code ATTRIBUTE_UNUSED
, int index_code
)
1224 if (regno
<= SP_REG
&& regno
>= 16)
1226 if (index_code
== REG
)
1227 return (regno
== HL_REG
);
1228 if (regno
== C_REG
|| regno
== B_REG
|| regno
== E_REG
|| regno
== L_REG
)
1233 /* Implements MODE_CODE_BASE_REG_CLASS. */
1235 rl78_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED
,
1236 addr_space_t address_space ATTRIBUTE_UNUSED
,
1237 int outer_code ATTRIBUTE_UNUSED
,
1238 int index_code ATTRIBUTE_UNUSED
)
1243 /* Typical stack layout should looks like this after the function's prologue:
1248 | | arguments saved | Increasing
1249 | | on the stack | addresses
1250 PARENT arg pointer -> | | /
1251 -------------------------- ---- -------------------
1252 CHILD |ret | return address
1257 frame pointer -> | | /
1265 | | outgoing | Decreasing
1266 | | arguments | addresses
1267 current stack pointer -> | | / |
1268 -------------------------- ---- ------------------ V
1271 /* Implements INITIAL_ELIMINATION_OFFSET. The frame layout is
1272 described in the machine_Function struct definition, above. */
1274 rl78_initial_elimination_offset (int from
, int to
)
1276 int rv
= 0; /* as if arg to arg */
1278 rl78_compute_frame_info ();
1282 case STACK_POINTER_REGNUM
:
1283 rv
+= cfun
->machine
->framesize_outgoing
;
1284 rv
+= cfun
->machine
->framesize_locals
;
1286 case FRAME_POINTER_REGNUM
:
1287 rv
+= cfun
->machine
->framesize_regs
;
1296 case FRAME_POINTER_REGNUM
:
1298 rv
-= cfun
->machine
->framesize_regs
;
1299 case ARG_POINTER_REGNUM
:
1309 rl78_is_naked_func (void)
1311 return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
)) != NULL_TREE
);
1314 /* Check if the block uses mul/div insns for G13 target. */
1317 check_mduc_usage (void)
1322 FOR_EACH_BB_FN (bb
, cfun
)
1324 FOR_BB_INSNS (bb
, insn
)
1327 && (get_attr_is_g13_muldiv_insn (insn
) == IS_G13_MULDIV_INSN_YES
))
1334 /* Expand the function prologue (from the prologue pattern). */
1337 rl78_expand_prologue (void)
1340 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1341 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1344 if (rl78_is_naked_func ())
1347 /* Always re-compute the frame info - the register usage may have changed. */
1348 rl78_compute_frame_info ();
1350 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1351 cfun
->machine
->framesize
+= ARRAY_SIZE (mduc_regs
) * 2;
1353 if (flag_stack_usage_info
)
1354 current_function_static_stack_size
= cfun
->machine
->framesize
;
1356 if (is_interrupt_func (cfun
->decl
) && !TARGET_G10
)
1357 for (i
= 0; i
< 4; i
++)
1358 if (cfun
->machine
->need_to_push
[i
])
1360 /* Select Bank 0 if we are using any registers from Bank 0. */
1361 emit_insn (gen_sel_rb (GEN_INT (0)));
1365 for (i
= 0; i
< 16; i
++)
1366 if (cfun
->machine
->need_to_push
[i
])
1374 emit_move_insn (ax
, gen_rtx_REG (HImode
, reg
));
1380 int need_bank
= i
/4;
1382 if (need_bank
!= rb
)
1384 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1389 F (emit_insn (gen_push (gen_rtx_REG (HImode
, reg
))));
1393 emit_insn (gen_sel_rb (GEN_INT (0)));
1395 /* Save ES register inside interrupt functions if it is used. */
1396 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1398 emit_insn (gen_movqi_from_es (gen_rtx_REG (QImode
, A_REG
)));
1399 F (emit_insn (gen_push (ax
)));
1402 /* Save MDUC registers inside interrupt routine. */
1403 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1405 for (unsigned i
= 0; i
< ARRAY_SIZE (mduc_regs
); i
++)
1407 mduc_reg_type
*reg
= mduc_regs
+ i
;
1408 rtx mem_mduc
= gen_rtx_MEM (reg
->mode
, GEN_INT (reg
->address
));
1410 MEM_VOLATILE_P (mem_mduc
) = 1;
1411 if (reg
->mode
== QImode
)
1412 emit_insn (gen_movqi (gen_rtx_REG (QImode
, A_REG
), mem_mduc
));
1414 emit_insn (gen_movhi (gen_rtx_REG (HImode
, AX_REG
), mem_mduc
));
1416 emit_insn (gen_push (gen_rtx_REG (HImode
, AX_REG
)));
1420 if (frame_pointer_needed
)
1422 F (emit_move_insn (ax
, sp
));
1423 F (emit_move_insn (gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
), ax
));
1426 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1429 /* If we need to subtract more than 254*3 then it is faster and
1430 smaller to move SP into AX and perform the subtraction there. */
1435 emit_move_insn (ax
, sp
);
1436 emit_insn (gen_subhi3 (ax
, ax
, GEN_INT (fs
)));
1437 insn
= F (emit_move_insn (sp
, ax
));
1438 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
,
1439 gen_rtx_SET (sp
, gen_rtx_PLUS (HImode
, sp
,
1446 int fs_byte
= (fs
> 254) ? 254 : fs
;
1448 F (emit_insn (gen_subhi3 (sp
, sp
, GEN_INT (fs_byte
))));
1455 /* Expand the function epilogue (from the epilogue pattern). */
1457 rl78_expand_epilogue (void)
1460 rtx sp
= gen_rtx_REG (HImode
, STACK_POINTER_REGNUM
);
1461 rtx ax
= gen_rtx_REG (HImode
, AX_REG
);
1464 if (rl78_is_naked_func ())
1467 if (frame_pointer_needed
)
1469 emit_move_insn (ax
, gen_rtx_REG (HImode
, FRAME_POINTER_REGNUM
));
1470 emit_move_insn (sp
, ax
);
1474 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
1477 emit_move_insn (ax
, sp
);
1478 emit_insn (gen_addhi3 (ax
, ax
, GEN_INT (fs
)));
1479 emit_move_insn (sp
, ax
);
1485 int fs_byte
= (fs
> 254) ? 254 : fs
;
1487 emit_insn (gen_addhi3 (sp
, sp
, GEN_INT (fs_byte
)));
1493 /* Restore MDUC registers from interrupt routine. */
1494 if (MUST_SAVE_MDUC_REGISTERS
&& (!crtl
->is_leaf
|| check_mduc_usage ()))
1496 for (int i
= ARRAY_SIZE (mduc_regs
) - 1; i
>= 0; i
--)
1498 mduc_reg_type
*reg
= mduc_regs
+ i
;
1499 rtx mem_mduc
= gen_rtx_MEM (reg
->mode
, GEN_INT (reg
->address
));
1501 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1502 MEM_VOLATILE_P (mem_mduc
) = 1;
1503 if (reg
->mode
== QImode
)
1504 emit_insn (gen_movqi (mem_mduc
, gen_rtx_REG (QImode
, A_REG
)));
1506 emit_insn (gen_movhi (mem_mduc
, gen_rtx_REG (HImode
, AX_REG
)));
1510 if (is_interrupt_func (cfun
->decl
) && cfun
->machine
->uses_es
)
1512 emit_insn (gen_pop (gen_rtx_REG (HImode
, AX_REG
)));
1513 emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode
, A_REG
)));
1516 for (i
= 15; i
>= 0; i
--)
1517 if (cfun
->machine
->need_to_push
[i
])
1519 rtx dest
= gen_rtx_REG (HImode
, i
* 2);
1524 emit_insn (gen_pop (dest
));
1527 emit_insn (gen_pop (ax
));
1528 emit_move_insn (dest
, ax
);
1529 /* Generate a USE of the pop'd register so that DCE will not eliminate the move. */
1530 emit_insn (gen_use (dest
));
1535 int need_bank
= i
/ 4;
1537 if (need_bank
!= rb
)
1539 emit_insn (gen_sel_rb (GEN_INT (need_bank
)));
1542 emit_insn (gen_pop (dest
));
1547 emit_insn (gen_sel_rb (GEN_INT (0)));
1549 if (cfun
->machine
->trampolines_used
)
1550 emit_insn (gen_trampoline_uninit ());
1552 if (is_brk_interrupt_func (cfun
->decl
))
1553 emit_jump_insn (gen_brk_interrupt_return ());
1554 else if (is_interrupt_func (cfun
->decl
))
1555 emit_jump_insn (gen_interrupt_return ());
1557 emit_jump_insn (gen_rl78_return ());
1560 /* Likewise, for exception handlers. */
1562 rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED
)
1564 /* FIXME - replace this with an indirect jump with stack adjust. */
1565 emit_jump_insn (gen_rl78_return ());
1568 #undef TARGET_ASM_FUNCTION_PROLOGUE
1569 #define TARGET_ASM_FUNCTION_PROLOGUE rl78_start_function
1571 /* We don't use this to actually emit the function prologue. We use
1572 this to insert a comment in the asm file describing the
1575 rl78_start_function (FILE *file
)
1579 if (cfun
->machine
->framesize
== 0)
1581 fprintf (file
, "\t; start of function\n");
1583 if (cfun
->machine
->framesize_regs
)
1585 fprintf (file
, "\t; push %d:", cfun
->machine
->framesize_regs
);
1586 for (i
= 0; i
< 16; i
++)
1587 if (cfun
->machine
->need_to_push
[i
])
1588 fprintf (file
, " %s", word_regnames
[i
*2]);
1589 fprintf (file
, "\n");
1592 if (frame_pointer_needed
)
1593 fprintf (file
, "\t; $fp points here (r22)\n");
1595 if (cfun
->machine
->framesize_locals
)
1596 fprintf (file
, "\t; locals: %d byte%s\n", cfun
->machine
->framesize_locals
,
1597 cfun
->machine
->framesize_locals
== 1 ? "" : "s");
1599 if (cfun
->machine
->framesize_outgoing
)
1600 fprintf (file
, "\t; outgoing: %d byte%s\n", cfun
->machine
->framesize_outgoing
,
1601 cfun
->machine
->framesize_outgoing
== 1 ? "" : "s");
1603 if (cfun
->machine
->uses_es
)
1604 fprintf (file
, "\t; uses ES register\n");
1606 if (MUST_SAVE_MDUC_REGISTERS
)
1607 fprintf (file
, "\t; preserves MDUC registers\n");
1610 /* Return an RTL describing where a function return value of type RET_TYPE
1613 #undef TARGET_FUNCTION_VALUE
1614 #define TARGET_FUNCTION_VALUE rl78_function_value
1617 rl78_function_value (const_tree ret_type
,
1618 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1619 bool outgoing ATTRIBUTE_UNUSED
)
1621 machine_mode mode
= TYPE_MODE (ret_type
);
1623 return gen_rtx_REG (mode
, 8);
1626 #undef TARGET_PROMOTE_FUNCTION_MODE
1627 #define TARGET_PROMOTE_FUNCTION_MODE rl78_promote_function_mode
1630 rl78_promote_function_mode (const_tree type ATTRIBUTE_UNUSED
,
1632 int *punsignedp ATTRIBUTE_UNUSED
,
1633 const_tree funtype ATTRIBUTE_UNUSED
, int for_return ATTRIBUTE_UNUSED
)
1638 /* Return an RTL expression describing the register holding a function
1639 parameter of mode MODE and type TYPE or NULL_RTX if the parameter should
1640 be passed on the stack. CUM describes the previous parameters to the
1641 function and NAMED is false if the parameter is part of a variable
1642 parameter list, or the last named parameter before the start of a
1643 variable parameter list. */
1645 #undef TARGET_FUNCTION_ARG
1646 #define TARGET_FUNCTION_ARG rl78_function_arg
1649 rl78_function_arg (cumulative_args_t cum_v ATTRIBUTE_UNUSED
,
1650 machine_mode mode ATTRIBUTE_UNUSED
,
1651 const_tree type ATTRIBUTE_UNUSED
,
1652 bool named ATTRIBUTE_UNUSED
)
1657 #undef TARGET_FUNCTION_ARG_ADVANCE
1658 #define TARGET_FUNCTION_ARG_ADVANCE rl78_function_arg_advance
1661 rl78_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
, const_tree type
,
1662 bool named ATTRIBUTE_UNUSED
)
1665 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
1667 rounded_size
= ((mode
== BLKmode
)
1668 ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
));
1669 if (rounded_size
& 1)
1671 (*cum
) += rounded_size
;
1674 #undef TARGET_FUNCTION_ARG_BOUNDARY
1675 #define TARGET_FUNCTION_ARG_BOUNDARY rl78_function_arg_boundary
1678 rl78_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED
,
1679 const_tree type ATTRIBUTE_UNUSED
)
1684 /* Supported modifier letters:
1686 A - address of a MEM
1687 S - SADDR form of a real register
1688 v - real register corresponding to a virtual register
1689 m - minus - negative of CONST_INT value.
1690 C - inverse of a conditional (NE vs EQ for example)
1691 C - complement of an integer
1692 z - collapsed conditional
1693 s - shift count mod 8
1694 S - shift count mod 16
1695 r - reverse shift count (8-(count mod 8))
1698 h - bottom HI of an SI
1700 q - bottom QI of an HI
1702 e - third QI of an SI (i.e. where the ES register gets values from)
1703 E - fourth QI of an SI (i.e. MSB)
1705 p - Add +0 to a zero-indexed HL based address.
1708 /* Implements the bulk of rl78_print_operand, below. We do it this
1709 way because we need to test for a constant at the top level and
1710 insert the '#', but not test for it anywhere else as we recurse
1711 down into the operand. */
1713 rl78_print_operand_1 (FILE * file
, rtx op
, int letter
)
1717 switch (GET_CODE (op
))
1721 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1724 if (rl78_far_p (op
))
1726 fprintf (file
, "es:");
1727 if (GET_CODE (XEXP (op
, 0)) == UNSPEC
)
1728 op
= gen_rtx_MEM (GET_MODE (op
), XVECEXP (XEXP (op
, 0), 0, 1));
1732 op
= adjust_address (op
, HImode
, 2);
1737 op
= adjust_address (op
, HImode
, 0);
1742 op
= adjust_address (op
, QImode
, 1);
1747 op
= adjust_address (op
, QImode
, 0);
1752 op
= adjust_address (op
, QImode
, 2);
1757 op
= adjust_address (op
, QImode
, 3);
1760 if (CONSTANT_P (XEXP (op
, 0)))
1762 if (!rl78_saddr_p (op
))
1763 fprintf (file
, "!");
1764 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1766 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1767 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
)
1769 if (!rl78_saddr_p (op
))
1770 fprintf (file
, "!");
1771 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1773 else if (GET_CODE (XEXP (op
, 0)) == PLUS
1774 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == REG
1775 && REGNO (XEXP (XEXP (op
, 0), 0)) == 2)
1777 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 1), 'u');
1778 fprintf (file
, "[");
1779 rl78_print_operand_1 (file
, XEXP (XEXP (op
, 0), 0), 0);
1780 if (letter
== 'p' && GET_CODE (XEXP (op
, 0)) == REG
)
1781 fprintf (file
, "+0");
1782 fprintf (file
, "]");
1787 fprintf (file
, "[");
1788 rl78_print_operand_1 (file
, op
, letter
);
1789 if (letter
== 'p' && REG_P (op
) && REGNO (op
) == 6)
1790 fprintf (file
, "+0");
1791 fprintf (file
, "]");
1798 fprintf (file
, "%s", reg_names
[REGNO (op
) | 1]);
1799 else if (letter
== 'H')
1800 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1801 else if (letter
== 'q')
1802 fprintf (file
, "%s", reg_names
[REGNO (op
) & ~1]);
1803 else if (letter
== 'e')
1804 fprintf (file
, "%s", reg_names
[REGNO (op
) + 2]);
1805 else if (letter
== 'E')
1806 fprintf (file
, "%s", reg_names
[REGNO (op
) + 3]);
1807 else if (letter
== 'S')
1808 fprintf (file
, "0x%x", 0xffef8 + REGNO (op
));
1809 else if (GET_MODE (op
) == HImode
1810 && ! (REGNO (op
) & ~0xfe))
1813 fprintf (file
, "%s", word_regnames
[REGNO (op
) % 8]);
1815 fprintf (file
, "%s", word_regnames
[REGNO (op
)]);
1818 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1823 fprintf (file
, "%ld", INTVAL (op
) >> 8);
1824 else if (letter
== 'H')
1825 fprintf (file
, "%ld", INTVAL (op
) >> 16);
1826 else if (letter
== 'q')
1827 fprintf (file
, "%ld", INTVAL (op
) & 0xff);
1828 else if (letter
== 'h')
1829 fprintf (file
, "%ld", INTVAL (op
) & 0xffff);
1830 else if (letter
== 'e')
1831 fprintf (file
, "%ld", (INTVAL (op
) >> 16) & 0xff);
1832 else if (letter
== 'B')
1834 int ival
= INTVAL (op
);
1837 if (exact_log2 (ival
) >= 0)
1838 fprintf (file
, "%d", exact_log2 (ival
));
1840 fprintf (file
, "%d", exact_log2 (~ival
& 0xff));
1842 else if (letter
== 'E')
1843 fprintf (file
, "%ld", (INTVAL (op
) >> 24) & 0xff);
1844 else if (letter
== 'm')
1845 fprintf (file
, "%ld", - INTVAL (op
));
1846 else if (letter
== 's')
1847 fprintf (file
, "%ld", INTVAL (op
) % 8);
1848 else if (letter
== 'S')
1849 fprintf (file
, "%ld", INTVAL (op
) % 16);
1850 else if (letter
== 'r')
1851 fprintf (file
, "%ld", 8 - (INTVAL (op
) % 8));
1852 else if (letter
== 'C')
1853 fprintf (file
, "%ld", (INTVAL (op
) ^ 0x8000) & 0xffff);
1855 fprintf (file
, "%ld", INTVAL (op
));
1859 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1864 int bits
= INTVAL (XEXP (op
, 1));
1865 int ofs
= INTVAL (XEXP (op
, 2));
1866 if (bits
== 16 && ofs
== 0)
1867 fprintf (file
, "%%lo16(");
1868 else if (bits
== 16 && ofs
== 16)
1869 fprintf (file
, "%%hi16(");
1870 else if (bits
== 8 && ofs
== 16)
1871 fprintf (file
, "%%hi8(");
1874 rl78_print_operand_1 (file
, XEXP (op
, 0), 0);
1875 fprintf (file
, ")");
1880 if (GET_CODE (XEXP (op
, 0)) == REG
)
1881 fprintf (file
, "%s", reg_names
[REGNO (XEXP (op
, 0))]);
1883 print_rtl (file
, op
);
1890 fprintf (file
, "%%hi16(");
1896 fprintf (file
, "%%lo16(");
1902 fprintf (file
, "%%hi8(");
1906 if (letter
== 'q' || letter
== 'Q')
1907 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1909 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTEND
)
1911 if (GET_CODE (XEXP (op
, 1)) == SYMBOL_REF
1912 && SYMBOL_REF_DECL (XEXP (op
, 1))
1913 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 1))) == FUNCTION_DECL
)
1915 fprintf (file
, "%%code(");
1916 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 1), 0)));
1917 fprintf (file
, "+");
1918 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1919 fprintf (file
, ")");
1923 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1924 fprintf (file
, "+");
1925 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1930 if (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1931 && SYMBOL_REF_DECL (XEXP (op
, 0))
1932 && TREE_CODE (SYMBOL_REF_DECL (XEXP (op
, 0))) == FUNCTION_DECL
)
1934 fprintf (file
, "%%code(");
1935 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (XEXP (op
, 0), 0)));
1936 fprintf (file
, "+");
1937 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1938 fprintf (file
, ")");
1942 rl78_print_operand_1 (file
, XEXP (op
, 0), letter
);
1943 fprintf (file
, "+");
1944 rl78_print_operand_1 (file
, XEXP (op
, 1), letter
);
1948 fprintf (file
, ")");
1952 if (GET_MODE (op
) == HImode
1953 && SUBREG_BYTE (op
) == 0)
1955 fprintf (file
, "%%lo16(");
1956 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1957 fprintf (file
, ")");
1959 else if (GET_MODE (op
) == HImode
1960 && SUBREG_BYTE (op
) == 2)
1962 fprintf (file
, "%%hi16(");
1963 rl78_print_operand_1 (file
, SUBREG_REG (op
), 0);
1964 fprintf (file
, ")");
1968 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
1976 fprintf (file
, "%%hi16(");
1982 fprintf (file
, "%%lo16(");
1988 fprintf (file
, "%%hi8(");
1992 if (letter
== 'q' || letter
== 'Q')
1993 output_operand_lossage ("q/Q modifiers invalid for symbol references");
1995 if (SYMBOL_REF_DECL (op
) && TREE_CODE (SYMBOL_REF_DECL (op
)) == FUNCTION_DECL
)
1997 fprintf (file
, "%%code(");
1998 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
1999 fprintf (file
, ")");
2002 assemble_name (file
, rl78_strip_nonasm_name_encoding (XSTR (op
, 0)));
2004 fprintf (file
, ")");
2009 output_asm_label (op
);
2014 fprintf (file
, "#comparison eliminated");
2016 fprintf (file
, letter
== 'C' ? "nc" : "c");
2020 fprintf (file
, "br");
2022 fprintf (file
, letter
== 'C' ? "h" : "nh");
2026 fprintf (file
, "br");
2028 fprintf (file
, letter
== 'C' ? "c" : "nc");
2032 fprintf (file
, "#comparison eliminated");
2034 fprintf (file
, letter
== 'C' ? "nh" : "h");
2038 fprintf (file
, "br");
2040 fprintf (file
, letter
== 'C' ? "nz" : "z");
2044 fprintf (file
, "#comparison eliminated");
2046 fprintf (file
, letter
== 'C' ? "z" : "nz");
2049 /* Note: these assume appropriate adjustments were made so that
2050 unsigned comparisons, which is all this chip has, will
2054 fprintf (file
, "#comparison eliminated");
2056 fprintf (file
, letter
== 'C' ? "nc" : "c");
2060 fprintf (file
, "br");
2062 fprintf (file
, letter
== 'C' ? "h" : "nh");
2066 fprintf (file
, "br");
2068 fprintf (file
, letter
== 'C' ? "c" : "nc");
2072 fprintf (file
, "#comparison eliminated");
2074 fprintf (file
, letter
== 'C' ? "nh" : "h");
2078 fprintf (file
, "(%s)", GET_RTX_NAME (GET_CODE (op
)));
2083 #undef TARGET_PRINT_OPERAND
2084 #define TARGET_PRINT_OPERAND rl78_print_operand
2087 rl78_print_operand (FILE * file
, rtx op
, int letter
)
2089 if (CONSTANT_P (op
) && letter
!= 'u' && letter
!= 's' && letter
!= 'r' && letter
!= 'S' && letter
!= 'B')
2090 fprintf (file
, "#");
2091 rl78_print_operand_1 (file
, op
, letter
);
2094 #undef TARGET_TRAMPOLINE_INIT
2095 #define TARGET_TRAMPOLINE_INIT rl78_trampoline_init
2097 /* Note that the RL78's addressing makes it very difficult to do
2098 trampolines on the stack. So, libgcc has a small pool of
2099 trampolines from which one is allocated to this task. */
2101 rl78_trampoline_init (rtx m_tramp
, tree fndecl
, rtx static_chain
)
2103 rtx mov_addr
, thunk_addr
;
2104 rtx function
= XEXP (DECL_RTL (fndecl
), 0);
2106 mov_addr
= adjust_address (m_tramp
, HImode
, 0);
2107 thunk_addr
= gen_reg_rtx (HImode
);
2109 function
= force_reg (HImode
, function
);
2110 static_chain
= force_reg (HImode
, static_chain
);
2112 emit_insn (gen_trampoline_init (thunk_addr
, function
, static_chain
));
2113 emit_move_insn (mov_addr
, thunk_addr
);
2115 cfun
->machine
->trampolines_used
= 1;
2118 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
2119 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS rl78_trampoline_adjust_address
2122 rl78_trampoline_adjust_address (rtx m_tramp
)
2124 rtx x
= gen_rtx_MEM (HImode
, m_tramp
);
2128 /* Expander for cbranchqi4 and cbranchhi4. RL78 is missing some of
2129 the "normal" compares, specifically, it only has unsigned compares,
2130 so we must synthesize the missing ones. */
2132 rl78_expand_compare (rtx
*operands
)
2134 if (GET_CODE (operands
[2]) == MEM
)
2135 operands
[2] = copy_to_mode_reg (GET_MODE (operands
[2]), operands
[2]);
2140 /* Define this to 1 if you are debugging the peephole optimizers. */
2141 #define DEBUG_PEEP 0
2143 /* Predicate used to enable the peephole2 patterns in rl78-virt.md.
2144 The default "word" size is a byte so we can effectively use all the
2145 registers, but we want to do 16-bit moves whenever possible. This
2146 function determines when such a move is an option. */
2148 rl78_peep_movhi_p (rtx
*operands
)
2153 /* (set (op0) (op1))
2154 (set (op2) (op3)) */
2156 if (! rl78_virt_insns_ok ())
2160 fprintf (stderr
, "\033[33m");
2161 debug_rtx (operands
[0]);
2162 debug_rtx (operands
[1]);
2163 debug_rtx (operands
[2]);
2164 debug_rtx (operands
[3]);
2165 fprintf (stderr
, "\033[0m");
2168 /* You can move a constant to memory as QImode, but not HImode. */
2169 if (GET_CODE (operands
[0]) == MEM
2170 && GET_CODE (operands
[1]) != REG
)
2173 fprintf (stderr
, "no peep: move constant to memory\n");
2178 if (rtx_equal_p (operands
[0], operands
[3]))
2181 fprintf (stderr
, "no peep: overlapping\n");
2186 for (i
= 0; i
< 2; i
++)
2188 if (GET_CODE (operands
[i
]) != GET_CODE (operands
[i
+2]))
2191 fprintf (stderr
, "no peep: different codes\n");
2195 if (GET_MODE (operands
[i
]) != GET_MODE (operands
[i
+2]))
2198 fprintf (stderr
, "no peep: different modes\n");
2203 switch (GET_CODE (operands
[i
]))
2207 if (REGNO (operands
[i
]) + 1 != REGNO (operands
[i
+2])
2208 || GET_MODE (operands
[i
]) != QImode
)
2211 fprintf (stderr
, "no peep: wrong regnos %d %d %d\n",
2212 REGNO (operands
[i
]), REGNO (operands
[i
+2]),
2217 if (! rl78_hard_regno_mode_ok (REGNO (operands
[i
]), HImode
))
2220 fprintf (stderr
, "no peep: reg %d not HI\n", REGNO (operands
[i
]));
2230 if (GET_MODE (operands
[i
]) != QImode
)
2232 if (MEM_ALIGN (operands
[i
]) < 16)
2234 a
= XEXP (operands
[i
], 0);
2235 if (GET_CODE (a
) == CONST
)
2237 if (GET_CODE (a
) == PLUS
)
2239 if (GET_CODE (a
) == CONST_INT
2243 fprintf (stderr
, "no peep: misaligned mem %d\n", i
);
2244 debug_rtx (operands
[i
]);
2248 m
= adjust_address (operands
[i
], QImode
, 1);
2249 if (! rtx_equal_p (m
, operands
[i
+2]))
2252 fprintf (stderr
, "no peep: wrong mem %d\n", i
);
2254 debug_rtx (operands
[i
+2]);
2262 fprintf (stderr
, "no peep: wrong rtx %d\n", i
);
2268 fprintf (stderr
, "\033[32mpeep!\033[0m\n");
2273 /* Likewise, when a peephole is activated, this function helps compute
2274 the new operands. */
2276 rl78_setup_peep_movhi (rtx
*operands
)
2280 for (i
= 0; i
< 2; i
++)
2282 switch (GET_CODE (operands
[i
]))
2285 operands
[i
+4] = gen_rtx_REG (HImode
, REGNO (operands
[i
]));
2289 operands
[i
+4] = GEN_INT ((INTVAL (operands
[i
]) & 0xff) + ((char) INTVAL (operands
[i
+2])) * 256);
2293 operands
[i
+4] = adjust_address (operands
[i
], HImode
, 0);
2303 How Devirtualization works in the RL78 GCC port
2307 The RL78 is an 8-bit port with some 16-bit operations. It has 32
2308 bytes of register space, in four banks, memory-mapped. One bank is
2309 the "selected" bank and holds the registers used for primary
2310 operations. Since the registers are memory mapped, often you can
2311 still refer to the unselected banks via memory accesses.
2315 The GCC port uses bank 0 as the "selected" registers (A, X, BC, etc)
2316 and refers to the other banks via their memory addresses, although
2317 they're treated as regular registers internally. These "virtual"
2318 registers are R8 through R23 (bank3 is reserved for asm-based
2319 interrupt handlers).
2321 There are four machine description files:
2323 rl78.md - common register-independent patterns and definitions
2324 rl78-expand.md - expanders
2325 rl78-virt.md - patterns that match BEFORE devirtualization
2326 rl78-real.md - patterns that match AFTER devirtualization
2328 At least through register allocation and reload, gcc is told that it
2329 can do pretty much anything - but may only use the virtual registers.
2330 GCC cannot properly create the varying addressing modes that the RL78
2331 supports in an efficient way.
2333 Sometime after reload, the RL78 backend "devirtualizes" the RTL. It
2334 uses the "valloc" attribute in rl78-virt.md for determining the rules
2335 by which it will replace virtual registers with real registers (or
2336 not) and how to make up addressing modes. For example, insns tagged
2337 with "ro1" have a single read-only parameter, which may need to be
2338 moved from memory/constant/vreg to a suitable real register. As part
2339 of devirtualization, a flag is toggled, disabling the rl78-virt.md
2340 patterns and enabling the rl78-real.md patterns. The new patterns'
2341 constraints are used to determine the real registers used. NOTE:
2342 patterns in rl78-virt.md essentially ignore the constrains and rely on
2343 predicates, where the rl78-real.md ones essentially ignore the
2344 predicates and rely on the constraints.
2346 The devirtualization pass is scheduled via the pass manager (despite
2347 being called "rl78_reorg") so it can be scheduled prior to var-track
2348 (the idea is to let gdb know about the new registers). Ideally, it
2349 would be scheduled right after pro/epilogue generation, so the
2350 post-reload optimizers could operate on the real registers, but when I
2351 tried that there were some issues building the target libraries.
2353 During devirtualization, a simple register move optimizer is run. It
2354 would be better to run a full CSE/propogation pass on it though, but
2355 that has not yet been attempted.
2358 #define DEBUG_ALLOC 0
2360 #define OP(x) (*recog_data.operand_loc[x])
2362 /* This array is used to hold knowledge about the contents of the
2363 real registers (A ... H), the memory-based registers (r8 ... r31)
2364 and the first NUM_STACK_LOCS words on the stack. We use this to
2365 avoid generating redundant move instructions.
2367 A value in the range 0 .. 31 indicates register A .. r31.
2368 A value in the range 32 .. 63 indicates stack slot (value - 32).
2369 A value of NOT_KNOWN indicates that the contents of that location
2372 #define NUM_STACK_LOCS 32
2373 #define NOT_KNOWN 127
2375 static unsigned char content_memory
[32 + NUM_STACK_LOCS
];
2377 static unsigned char saved_update_index
= NOT_KNOWN
;
2378 static unsigned char saved_update_value
;
2379 static machine_mode saved_update_mode
;
2383 clear_content_memory (void)
2385 memset (content_memory
, NOT_KNOWN
, sizeof content_memory
);
2387 fprintf (dump_file
, " clear content memory\n");
2388 saved_update_index
= NOT_KNOWN
;
2391 /* Convert LOC into an index into the content_memory array.
2392 If LOC cannot be converted, return NOT_KNOWN. */
2394 static unsigned char
2395 get_content_index (rtx loc
)
2399 if (loc
== NULL_RTX
)
2404 if (REGNO (loc
) < 32)
2409 mode
= GET_MODE (loc
);
2411 if (! rl78_stack_based_mem (loc
, mode
))
2414 loc
= XEXP (loc
, 0);
2417 /* loc = MEM (SP) */
2420 /* loc = MEM (PLUS (SP, INT)). */
2421 loc
= XEXP (loc
, 1);
2423 if (INTVAL (loc
) < NUM_STACK_LOCS
)
2424 return 32 + INTVAL (loc
);
2429 /* Return a string describing content INDEX in mode MODE.
2430 WARNING: Can return a pointer to a static buffer. */
2432 get_content_name (unsigned char index
, machine_mode mode
)
2434 static char buffer
[128];
2436 if (index
== NOT_KNOWN
)
2440 sprintf (buffer
, "stack slot %d", index
- 32);
2441 else if (mode
== HImode
)
2442 sprintf (buffer
, "%s%s",
2443 reg_names
[index
+ 1], reg_names
[index
]);
2445 return reg_names
[index
];
2453 display_content_memory (FILE * file
)
2457 fprintf (file
, " Known memory contents:\n");
2459 for (i
= 0; i
< sizeof content_memory
; i
++)
2460 if (content_memory
[i
] != NOT_KNOWN
)
2462 fprintf (file
, " %s contains a copy of ", get_content_name (i
, QImode
));
2463 fprintf (file
, "%s\n", get_content_name (content_memory
[i
], QImode
));
2469 update_content (unsigned char index
, unsigned char val
, machine_mode mode
)
2473 gcc_assert (index
< sizeof content_memory
);
2475 content_memory
[index
] = val
;
2476 if (val
!= NOT_KNOWN
)
2477 content_memory
[val
] = index
;
2479 /* Make the entry in dump_file *before* VAL is increased below. */
2482 fprintf (dump_file
, " %s now contains ", get_content_name (index
, mode
));
2483 if (val
== NOT_KNOWN
)
2484 fprintf (dump_file
, "Unknown\n");
2486 fprintf (dump_file
, "%s and vice versa\n", get_content_name (val
, mode
));
2491 val
= val
== NOT_KNOWN
? val
: val
+ 1;
2493 content_memory
[index
+ 1] = val
;
2494 if (val
!= NOT_KNOWN
)
2496 content_memory
[val
] = index
+ 1;
2501 /* Any other places that had INDEX recorded as their contents are now invalid. */
2502 for (i
= 0; i
< sizeof content_memory
; i
++)
2505 || (val
!= NOT_KNOWN
&& i
== val
))
2512 if (content_memory
[i
] == index
2513 || (val
!= NOT_KNOWN
&& content_memory
[i
] == val
))
2515 content_memory
[i
] = NOT_KNOWN
;
2518 fprintf (dump_file
, " %s cleared\n", get_content_name (i
, mode
));
2521 content_memory
[++ i
] = NOT_KNOWN
;
2526 /* Record that LOC contains VALUE.
2527 For HImode locations record that LOC+1 contains VALUE+1.
2528 If LOC is not a register or stack slot, do nothing.
2529 If VALUE is not a register or stack slot, clear the recorded content. */
2532 record_content (rtx loc
, rtx value
)
2535 unsigned char index
;
2538 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2541 val
= get_content_index (value
);
2543 mode
= GET_MODE (loc
);
2550 /* This should not happen when optimizing. */
2552 fprintf (stderr
, "ASSIGNMENT of location to itself detected! [%s]\n",
2553 get_content_name (val
, mode
));
2560 update_content (index
, val
, mode
);
2563 /* Returns TRUE if LOC already contains a copy of VALUE. */
2566 already_contains (rtx loc
, rtx value
)
2568 unsigned char index
;
2571 if ((index
= get_content_index (loc
)) == NOT_KNOWN
)
2574 if ((val
= get_content_index (value
)) == NOT_KNOWN
)
2577 if (content_memory
[index
] != val
)
2580 if (GET_MODE (loc
) == HImode
)
2581 return content_memory
[index
+ 1] == val
+ 1;
2587 rl78_es_addr (rtx addr
)
2589 if (GET_CODE (addr
) == MEM
)
2590 addr
= XEXP (addr
, 0);
2591 if (GET_CODE (addr
) != UNSPEC
)
2593 if (XINT (addr
, 1) != UNS_ES_ADDR
)
2599 rl78_es_base (rtx addr
)
2601 if (GET_CODE (addr
) == MEM
)
2602 addr
= XEXP (addr
, 0);
2603 addr
= XVECEXP (addr
, 0, 1);
2604 if (GET_CODE (addr
) == CONST
2605 && GET_CODE (XEXP (addr
, 0)) == ZERO_EXTRACT
)
2606 addr
= XEXP (XEXP (addr
, 0), 0);
2607 /* Mode doesn't matter here. */
2608 return gen_rtx_MEM (HImode
, addr
);
2611 /* Rescans an insn to see if it's recognized again. This is done
2612 carefully to ensure that all the constraint information is accurate
2613 for the newly matched insn. */
2615 insn_ok_now (rtx_insn
* insn
)
2617 rtx pattern
= PATTERN (insn
);
2620 INSN_CODE (insn
) = -1;
2622 if (recog (pattern
, insn
, 0) > -1)
2624 extract_insn (insn
);
2625 if (constrain_operands (1, get_preferred_alternatives (insn
)))
2628 fprintf (stderr
, "\033[32m");
2630 fprintf (stderr
, "\033[0m");
2632 if (SET_P (pattern
))
2633 record_content (SET_DEST (pattern
), SET_SRC (pattern
));
2635 /* We need to detect far addresses that haven't been
2636 converted to es/lo16 format. */
2637 for (i
=0; i
<recog_data
.n_operands
; i
++)
2638 if (GET_CODE (OP (i
)) == MEM
2639 && GET_MODE (XEXP (OP (i
), 0)) == SImode
2640 && GET_CODE (XEXP (OP (i
), 0)) != UNSPEC
)
2648 /* We need to re-recog the insn with virtual registers to get
2650 cfun
->machine
->virt_insns_ok
= 1;
2651 if (recog (pattern
, insn
, 0) > -1)
2653 extract_insn (insn
);
2654 if (constrain_operands (0, get_preferred_alternatives (insn
)))
2656 cfun
->machine
->virt_insns_ok
= 0;
2662 fprintf (stderr
, "\033[41;30m Unrecognized *virtual* insn \033[0m\n");
2669 fprintf (stderr
, "\033[31m");
2671 fprintf (stderr
, "\033[0m");
2677 #define WORKED fprintf (stderr, "\033[48;5;22m Worked at line %d \033[0m\n", __LINE__)
2678 #define FAILEDSOFAR fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__)
2679 #define FAILED fprintf (stderr, "\033[48;5;52m FAILED at line %d \033[0m\n", __LINE__), gcc_unreachable ()
2680 #define MAYBE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } else { FAILEDSOFAR; }
2681 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) { WORKED; return; } FAILED
2683 #define FAILED gcc_unreachable ()
2684 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
2685 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
2688 /* Registers into which we move the contents of virtual registers. */
2689 #define X gen_rtx_REG (QImode, X_REG)
2690 #define A gen_rtx_REG (QImode, A_REG)
2691 #define C gen_rtx_REG (QImode, C_REG)
2692 #define B gen_rtx_REG (QImode, B_REG)
2693 #define E gen_rtx_REG (QImode, E_REG)
2694 #define D gen_rtx_REG (QImode, D_REG)
2695 #define L gen_rtx_REG (QImode, L_REG)
2696 #define H gen_rtx_REG (QImode, H_REG)
2698 #define AX gen_rtx_REG (HImode, AX_REG)
2699 #define BC gen_rtx_REG (HImode, BC_REG)
2700 #define DE gen_rtx_REG (HImode, DE_REG)
2701 #define HL gen_rtx_REG (HImode, HL_REG)
2703 /* Returns TRUE if R is a virtual register. */
2705 is_virtual_register (rtx r
)
2707 return (GET_CODE (r
) == REG
2712 /* In all these alloc routines, we expect the following: the insn
2713 pattern is unshared, the insn was previously recognized and failed
2714 due to predicates or constraints, and the operand data is in
2717 static int virt_insn_was_frame
;
2719 /* Hook for all insns we emit. Re-mark them as FRAME_RELATED if
2722 EM2 (int line ATTRIBUTE_UNUSED
, rtx r
)
2725 fprintf (stderr
, "\033[36m%d: ", line
);
2727 fprintf (stderr
, "\033[0m");
2729 /*SCHED_GROUP_P (r) = 1;*/
2730 if (virt_insn_was_frame
)
2731 RTX_FRAME_RELATED_P (r
) = 1;
2735 #define EM(x) EM2 (__LINE__, x)
2737 /* Return a suitable RTX for the low half of a __far address. */
2739 rl78_lo16 (rtx addr
)
2743 if (GET_CODE (addr
) == SYMBOL_REF
2744 || GET_CODE (addr
) == CONST
)
2746 r
= gen_rtx_ZERO_EXTRACT (HImode
, addr
, GEN_INT (16), GEN_INT (0));
2747 r
= gen_rtx_CONST (HImode
, r
);
2750 r
= rl78_subreg (HImode
, addr
, SImode
, 0);
2752 r
= gen_es_addr (r
);
2753 cfun
->machine
->uses_es
= true;
2758 /* Return a suitable RTX for the high half's lower byte of a __far address. */
2762 if (GET_CODE (addr
) == SYMBOL_REF
2763 || GET_CODE (addr
) == CONST
)
2765 rtx r
= gen_rtx_ZERO_EXTRACT (QImode
, addr
, GEN_INT (8), GEN_INT (16));
2766 r
= gen_rtx_CONST (QImode
, r
);
2769 return rl78_subreg (QImode
, addr
, SImode
, 2);
2773 add_postponed_content_update (rtx to
, rtx value
)
2775 unsigned char index
;
2777 if ((index
= get_content_index (to
)) == NOT_KNOWN
)
2780 gcc_assert (saved_update_index
== NOT_KNOWN
);
2781 saved_update_index
= index
;
2782 saved_update_value
= get_content_index (value
);
2783 saved_update_mode
= GET_MODE (to
);
2787 process_postponed_content_update (void)
2789 if (saved_update_index
!= NOT_KNOWN
)
2791 update_content (saved_update_index
, saved_update_value
, saved_update_mode
);
2792 saved_update_index
= NOT_KNOWN
;
2796 /* Generate and emit a move of (register) FROM into TO. if WHERE is not NULL
2797 then if BEFORE is true then emit the insn before WHERE, otherwise emit it
2798 after WHERE. If TO already contains FROM then do nothing. Returns TO if
2799 BEFORE is true, FROM otherwise. */
2801 gen_and_emit_move (rtx to
, rtx from
, rtx_insn
*where
, bool before
)
2803 machine_mode mode
= GET_MODE (to
);
2805 if (optimize
&& before
&& already_contains (to
, from
))
2808 display_content_memory (stderr
);
2812 fprintf (dump_file
, " Omit move of %s into ",
2813 get_content_name (get_content_index (from
), mode
));
2814 fprintf (dump_file
, "%s as it already contains this value\n",
2815 get_content_name (get_content_index (to
), mode
));
2820 rtx move
= mode
== QImode
? gen_movqi (to
, from
) : gen_movhi (to
, from
);
2824 if (where
== NULL_RTX
)
2827 emit_insn_before (move
, where
);
2830 rtx note
= find_reg_note (where
, REG_EH_REGION
, NULL_RTX
);
2832 /* If necessary move REG_EH_REGION notes forward.
2833 cf. compiling gcc.dg/pr44545.c. */
2834 if (note
!= NULL_RTX
)
2836 add_reg_note (move
, REG_EH_REGION
, XEXP (note
, 0));
2837 remove_note (where
, note
);
2840 emit_insn_after (move
, where
);
2844 record_content (to
, from
);
2846 add_postponed_content_update (to
, from
);
2849 return before
? to
: from
;
2852 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
2853 copy it into NEWBASE and return the updated MEM. Otherwise just
2854 return M. Any needed insns are emitted before BEFORE. */
2856 transcode_memory_rtx (rtx m
, rtx newbase
, rtx_insn
*before
)
2858 rtx base
, index
, addendr
;
2865 if (GET_MODE (XEXP (m
, 0)) == SImode
)
2868 rtx seg
= rl78_hi8 (XEXP (m
, 0));
2872 emit_insn_before (EM (gen_movqi (A
, seg
)), before
);
2873 emit_insn_before (EM (gen_movqi_to_es (A
)), before
);
2876 record_content (A
, NULL_RTX
);
2878 new_m
= gen_rtx_MEM (GET_MODE (m
), rl78_lo16 (XEXP (m
, 0)));
2879 MEM_COPY_ATTRIBUTES (new_m
, m
);
2884 characterize_address (XEXP (m
, 0), & base
, & index
, & addendr
);
2885 gcc_assert (index
== NULL_RTX
);
2887 if (base
== NULL_RTX
)
2890 if (addendr
&& GET_CODE (addendr
) == CONST_INT
)
2891 addend
= INTVAL (addendr
);
2893 gcc_assert (REG_P (base
));
2894 gcc_assert (REG_P (newbase
));
2896 int limit
= 256 - GET_MODE_SIZE (GET_MODE (m
));
2898 if (REGNO (base
) == SP_REG
)
2900 if (addend
>= 0 && addend
<= limit
)
2904 /* BASE should be a virtual register. We copy it to NEWBASE. If
2905 the addend is out of range for DE/HL, we use AX to compute the full
2909 || (addend
> limit
&& REGNO (newbase
) != BC_REG
)
2911 && (GET_CODE (addendr
) != CONST_INT
)
2912 && ((REGNO (newbase
) != BC_REG
))
2918 EM (emit_insn_before (gen_movhi (AX
, base
), before
));
2919 EM (emit_insn_before (gen_addhi3 (AX
, AX
, addendr
), before
));
2920 EM (emit_insn_before (gen_movhi (newbase
, AX
), before
));
2921 record_content (AX
, NULL_RTX
);
2922 record_content (newbase
, NULL_RTX
);
2930 base
= gen_and_emit_move (newbase
, base
, before
, true);
2935 record_content (base
, NULL_RTX
);
2936 base
= gen_rtx_PLUS (HImode
, base
, GEN_INT (addend
));
2940 record_content (base
, NULL_RTX
);
2941 base
= gen_rtx_PLUS (HImode
, base
, addendr
);
2946 m
= change_address (m
, GET_MODE (m
), gen_es_addr (base
));
2947 cfun
->machine
->uses_es
= true;
2950 m
= change_address (m
, GET_MODE (m
), base
);
2954 /* Copy SRC to accumulator (A or AX), placing any generated insns
2955 before BEFORE. Returns accumulator RTX. */
2957 move_to_acc (int opno
, rtx_insn
*before
)
2959 rtx src
= OP (opno
);
2960 machine_mode mode
= GET_MODE (src
);
2962 if (REG_P (src
) && REGNO (src
) < 2)
2965 if (mode
== VOIDmode
)
2966 mode
= recog_data
.operand_mode
[opno
];
2968 return gen_and_emit_move (mode
== QImode
? A
: AX
, src
, before
, true);
2972 force_into_acc (rtx src
, rtx_insn
*before
)
2974 machine_mode mode
= GET_MODE (src
);
2977 if (REG_P (src
) && REGNO (src
) < 2)
2980 move
= mode
== QImode
? gen_movqi (A
, src
) : gen_movhi (AX
, src
);
2984 emit_insn_before (move
, before
);
2985 record_content (AX
, NULL_RTX
);
2988 /* Copy accumulator (A or AX) to DEST, placing any generated insns
2989 after AFTER. Returns accumulator RTX. */
2991 move_from_acc (unsigned int opno
, rtx_insn
*after
)
2993 rtx dest
= OP (opno
);
2994 machine_mode mode
= GET_MODE (dest
);
2996 if (REG_P (dest
) && REGNO (dest
) < 2)
2999 return gen_and_emit_move (dest
, mode
== QImode
? A
: AX
, after
, false);
3002 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
3003 before BEFORE. Returns reg RTX. */
3005 move_acc_to_reg (rtx acc
, int regno
, rtx_insn
*before
)
3007 machine_mode mode
= GET_MODE (acc
);
3010 reg
= gen_rtx_REG (mode
, regno
);
3012 return gen_and_emit_move (reg
, acc
, before
, true);
3015 /* Copy SRC to X, placing any generated insns before BEFORE.
3018 move_to_x (int opno
, rtx_insn
*before
)
3020 rtx src
= OP (opno
);
3021 machine_mode mode
= GET_MODE (src
);
3024 if (mode
== VOIDmode
)
3025 mode
= recog_data
.operand_mode
[opno
];
3026 reg
= (mode
== QImode
) ? X
: AX
;
3028 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3030 OP (opno
) = move_to_acc (opno
, before
);
3031 OP (opno
) = move_acc_to_reg (OP (opno
), X_REG
, before
);
3035 return gen_and_emit_move (reg
, src
, before
, true);
3038 /* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
3039 Returns H/HL RTX. */
3041 move_to_hl (int opno
, rtx_insn
*before
)
3043 rtx src
= OP (opno
);
3044 machine_mode mode
= GET_MODE (src
);
3047 if (mode
== VOIDmode
)
3048 mode
= recog_data
.operand_mode
[opno
];
3049 reg
= (mode
== QImode
) ? L
: HL
;
3051 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3053 OP (opno
) = move_to_acc (opno
, before
);
3054 OP (opno
) = move_acc_to_reg (OP (opno
), L_REG
, before
);
3058 return gen_and_emit_move (reg
, src
, before
, true);
3061 /* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
3062 Returns E/DE RTX. */
3064 move_to_de (int opno
, rtx_insn
*before
)
3066 rtx src
= OP (opno
);
3067 machine_mode mode
= GET_MODE (src
);
3070 if (mode
== VOIDmode
)
3071 mode
= recog_data
.operand_mode
[opno
];
3073 reg
= (mode
== QImode
) ? E
: DE
;
3075 if (mode
== QImode
|| ! is_virtual_register (OP (opno
)))
3077 OP (opno
) = move_to_acc (opno
, before
);
3078 OP (opno
) = move_acc_to_reg (OP (opno
), E_REG
, before
);
3082 gen_and_emit_move (reg
, src
, before
, true);
3088 /* Devirtualize an insn of the form (SET (op) (unop (op))). */
3090 rl78_alloc_physical_registers_op1 (rtx_insn
* insn
)
3092 /* op[0] = func op[1] */
3094 /* We first try using A as the destination, then copying it
3096 if (rtx_equal_p (OP (0), OP (1)))
3099 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3103 /* If necessary, load the operands into BC and HL.
3104 Check to see if we already have OP (0) in HL
3105 and if so, swap the order.
3107 It is tempting to perform this optimization when OP(0) does
3108 not hold a MEM, but this leads to bigger code in general.
3109 The problem is that if OP(1) holds a MEM then swapping it
3110 into BC means a BC-relative load is used and these are 3
3111 bytes long vs 1 byte for an HL load. */
3113 && already_contains (HL
, XEXP (OP (0), 0)))
3115 OP (0) = transcode_memory_rtx (OP (0), HL
, insn
);
3116 OP (1) = transcode_memory_rtx (OP (1), BC
, insn
);
3120 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3121 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3127 OP (0) = move_from_acc (0, insn
);
3131 /* Try copying the src to acc first, then. This is for, for
3132 example, ZERO_EXTEND or NOT. */
3133 OP (1) = move_to_acc (1, insn
);
3138 /* Returns true if operand OPNUM contains a constraint of type CONSTRAINT.
3139 Assumes that the current insn has already been recognised and hence the
3140 constraint data has been filled in. */
3142 has_constraint (unsigned int opnum
, enum constraint_num constraint
)
3144 const char * p
= recog_data
.constraints
[opnum
];
3146 /* No constraints means anything is accepted. */
3147 if (p
== NULL
|| *p
== 0 || *p
== ',')
3156 len
= CONSTRAINT_LEN (c
, p
);
3157 gcc_assert (len
> 0);
3165 if (lookup_constraint (p
) == constraint
)
3173 /* Devirtualize an insn of the form (SET (op) (binop (op) (op))). */
3175 rl78_alloc_physical_registers_op2 (rtx_insn
* insn
)
3183 if (rtx_equal_p (OP (0), OP (1)))
3188 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3189 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3194 OP (1) = transcode_memory_rtx (OP (1), HL
, insn
);
3195 OP (2) = transcode_memory_rtx (OP (2), DE
, insn
);
3198 else if (rtx_equal_p (OP (0), OP (2)))
3200 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3202 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3206 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3207 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3208 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3213 prev
= prev_nonnote_nondebug_insn (insn
);
3214 if (recog_data
.constraints
[1][0] == '%'
3215 && is_virtual_register (OP (1))
3216 && ! is_virtual_register (OP (2))
3217 && ! CONSTANT_P (OP (2)))
3224 /* Make a note of whether (H)L is being used. It matters
3225 because if OP (2) also needs reloading, then we must take
3226 care not to corrupt HL. */
3227 hl_used
= reg_mentioned_p (L
, OP (0)) || reg_mentioned_p (L
, OP (1));
3229 /* If HL is not currently being used and dest == op1 then there are
3230 some possible optimizations available by reloading one of the
3231 operands into HL, before trying to use the accumulator. */
3234 && rtx_equal_p (OP (0), OP (1)))
3236 /* If op0 is a Ws1 type memory address then switching the base
3237 address register to HL might allow us to perform an in-memory
3238 operation. (eg for the INCW instruction).
3240 FIXME: Adding the move into HL is costly if this optimization is not
3241 going to work, so for now, make sure that we know that the new insn will
3242 match the requirements of the addhi3_real pattern. Really we ought to
3243 generate a candidate sequence, test that, and then install it if the
3244 results are good. */
3245 if (satisfies_constraint_Ws1 (OP (0))
3246 && has_constraint (0, CONSTRAINT_Wh1
)
3247 && (satisfies_constraint_K (OP (2)) || satisfies_constraint_L (OP (2))))
3249 rtx base
, index
, addend
, newbase
;
3251 characterize_address (XEXP (OP (0), 0), & base
, & index
, & addend
);
3252 gcc_assert (index
== NULL_RTX
);
3253 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3255 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3256 if (addend
!= NULL_RTX
)
3258 newbase
= gen_and_emit_move (HL
, base
, insn
, true);
3259 record_content (newbase
, NULL_RTX
);
3260 newbase
= gen_rtx_PLUS (HImode
, newbase
, addend
);
3262 OP (0) = OP (1) = change_address (OP (0), VOIDmode
, newbase
);
3264 /* We do not want to fail here as this means that
3265 we have inserted useless insns into the stream. */
3269 else if (REG_P (OP (0))
3270 && satisfies_constraint_Ws1 (OP (2))
3271 && has_constraint (2, CONSTRAINT_Wh1
))
3273 rtx base
, index
, addend
, newbase
;
3275 characterize_address (XEXP (OP (2), 0), & base
, & index
, & addend
);
3276 gcc_assert (index
== NULL_RTX
);
3277 gcc_assert (REG_P (base
) && REGNO (base
) == SP_REG
);
3279 /* Ws1 addressing allows an offset of 0, Wh1 addressing requires a non-zero offset. */
3280 if (addend
!= NULL_RTX
)
3282 gen_and_emit_move (HL
, base
, insn
, true);
3284 if (REGNO (OP (0)) != X_REG
)
3286 OP (1) = move_to_acc (1, insn
);
3287 OP (0) = move_from_acc (0, insn
);
3290 record_content (HL
, NULL_RTX
);
3291 newbase
= gen_rtx_PLUS (HImode
, HL
, addend
);
3293 OP (2) = change_address (OP (2), VOIDmode
, newbase
);
3295 /* We do not want to fail here as this means that
3296 we have inserted useless insns into the stream. */
3302 OP (0) = move_from_acc (0, insn
);
3304 tmp_id
= get_max_insn_count ();
3307 if (rtx_equal_p (OP (1), OP (2)))
3308 OP (2) = OP (1) = move_to_acc (1, insn
);
3310 OP (1) = move_to_acc (1, insn
);
3314 /* If we omitted the move of OP1 into the accumulator (because
3315 it was already there from a previous insn), then force the
3316 generation of the move instruction now. We know that we
3317 are about to emit a move into HL (or DE) via AX, and hence
3318 our optimization to remove the load of OP1 is no longer valid. */
3319 if (tmp_id
== get_max_insn_count ())
3320 force_into_acc (saved_op1
, insn
);
3322 /* We have to copy op2 to HL (or DE), but that involves AX, which
3323 already has a live value. Emit it before those insns. */
3326 first
= next_nonnote_nondebug_insn (prev
);
3328 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3331 OP (2) = hl_used
? move_to_de (2, first
) : move_to_hl (2, first
);
3336 /* Devirtualize an insn of the form SET (PC) (MEM/REG). */
3338 rl78_alloc_physical_registers_ro1 (rtx_insn
* insn
)
3340 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3344 OP (0) = move_to_acc (0, insn
);
3349 /* Devirtualize a compare insn. */
3351 rl78_alloc_physical_registers_cmp (rtx_insn
* insn
)
3355 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3358 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3359 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3361 /* HI compares have to have OP (1) in AX, but QI
3362 compares do not, so it is worth checking here. */
3365 /* For an HImode compare, OP (1) must always be in AX.
3366 But if OP (1) is a REG (and not AX), then we can avoid
3367 a reload of OP (1) if we reload OP (2) into AX and invert
3370 && REGNO (OP (1)) != AX_REG
3371 && GET_MODE (OP (1)) == HImode
3374 rtx cmp
= XEXP (SET_SRC (PATTERN (insn
)), 0);
3376 OP (2) = move_to_acc (2, insn
);
3378 switch (GET_CODE (cmp
))
3383 case LTU
: cmp
= gen_rtx_GTU (HImode
, OP (2), OP (1)); break;
3384 case GTU
: cmp
= gen_rtx_LTU (HImode
, OP (2), OP (1)); break;
3385 case LEU
: cmp
= gen_rtx_GEU (HImode
, OP (2), OP (1)); break;
3386 case GEU
: cmp
= gen_rtx_LEU (HImode
, OP (2), OP (1)); break;
3399 if (GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
3400 PATTERN (insn
) = gen_cbranchhi4_real (cmp
, OP (2), OP (1), OP (3));
3402 PATTERN (insn
) = gen_cbranchhi4_real_inverted (cmp
, OP (2), OP (1), OP (3));
3407 /* Surprisingly, gcc can generate a comparison of a register with itself, but this
3408 should be handled by the second alternative of the cbranchhi_real pattern. */
3409 if (rtx_equal_p (OP (1), OP (2)))
3411 OP (1) = OP (2) = BC
;
3415 tmp_id
= get_max_insn_count ();
3418 OP (1) = move_to_acc (1, insn
);
3422 /* If we omitted the move of OP1 into the accumulator (because
3423 it was already there from a previous insn), then force the
3424 generation of the move instruction now. We know that we
3425 are about to emit a move into HL via AX, and hence our
3426 optimization to remove the load of OP1 is no longer valid. */
3427 if (tmp_id
== get_max_insn_count ())
3428 force_into_acc (saved_op1
, insn
);
3430 /* We have to copy op2 to HL, but that involves the acc, which
3431 already has a live value. Emit it before those insns. */
3433 first
= next_nonnote_nondebug_insn (prev
);
3435 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3437 OP (2) = move_to_hl (2, first
);
3442 /* Like op2, but AX = A * X. */
3444 rl78_alloc_physical_registers_umul (rtx_insn
* insn
)
3446 rtx_insn
*prev
= prev_nonnote_nondebug_insn (insn
);
3451 OP (0) = transcode_memory_rtx (OP (0), BC
, insn
);
3452 OP (1) = transcode_memory_rtx (OP (1), DE
, insn
);
3453 OP (2) = transcode_memory_rtx (OP (2), HL
, insn
);
3457 if (recog_data
.constraints
[1][0] == '%'
3458 && is_virtual_register (OP (1))
3459 && !is_virtual_register (OP (2))
3460 && !CONSTANT_P (OP (2)))
3467 OP (0) = move_from_acc (0, insn
);
3469 tmp_id
= get_max_insn_count ();
3472 if (rtx_equal_p (OP (1), OP (2)))
3474 gcc_assert (GET_MODE (OP (2)) == QImode
);
3475 /* The MULU instruction does not support duplicate arguments
3476 but we know that if we copy OP (2) to X it will do so via
3477 A and thus OP (1) will already be loaded into A. */
3478 OP (2) = move_to_x (2, insn
);
3482 OP (1) = move_to_acc (1, insn
);
3486 /* If we omitted the move of OP1 into the accumulator (because
3487 it was already there from a previous insn), then force the
3488 generation of the move instruction now. We know that we
3489 are about to emit a move into HL (or DE) via AX, and hence
3490 our optimization to remove the load of OP1 is no longer valid. */
3491 if (tmp_id
== get_max_insn_count ())
3492 force_into_acc (saved_op1
, insn
);
3494 /* We have to copy op2 to X, but that involves the acc, which
3495 already has a live value. Emit it before those insns. */
3498 first
= next_nonnote_nondebug_insn (prev
);
3500 for (first
= insn
; prev_nonnote_nondebug_insn (first
); first
= prev_nonnote_nondebug_insn (first
))
3502 OP (2) = move_to_x (2, first
);
3508 rl78_alloc_address_registers_macax (rtx_insn
* insn
)
3511 bool replace_in_op0
= false;
3512 bool replace_in_op1
= false;
3516 /* Two different MEMs are not allowed. */
3518 for (op
= 2; op
>= 0; op
--)
3520 if (MEM_P (OP (op
)))
3522 if (op
== 0 && replace_in_op0
)
3524 if (op
== 1 && replace_in_op1
)
3530 /* If we replace a MEM, make sure that we replace it for all
3531 occurrences of the same MEM in the insn. */
3532 replace_in_op0
= (op
> 0 && rtx_equal_p (OP (op
), OP (0)));
3533 replace_in_op1
= (op
> 1 && rtx_equal_p (OP (op
), OP (1)));
3535 OP (op
) = transcode_memory_rtx (OP (op
), HL
, insn
);
3538 && ((GET_CODE (XEXP (OP (op
), 0)) == REG
3539 && REGNO (XEXP (OP (op
), 0)) == SP_REG
)
3540 || (GET_CODE (XEXP (OP (op
), 0)) == PLUS
3541 && REGNO (XEXP (XEXP (OP (op
), 0), 0)) == SP_REG
)))
3543 emit_insn_before (gen_movhi (HL
, gen_rtx_REG (HImode
, SP_REG
)), insn
);
3544 OP (op
) = replace_rtx (OP (op
), gen_rtx_REG (HImode
, SP_REG
), HL
);
3552 OP (op
) = transcode_memory_rtx (OP (op
), DE
, insn
);
3555 OP (op
) = transcode_memory_rtx (OP (op
), BC
, insn
);
3566 rl78_alloc_address_registers_div (rtx_insn
* insn
)
3571 /* Scan all insns and devirtualize them. */
3573 rl78_alloc_physical_registers (void)
3575 /* During most of the compile, gcc is dealing with virtual
3576 registers. At this point, we need to assign physical registers
3577 to the vitual ones, and copy in/out as needed. */
3579 rtx_insn
*insn
, *curr
;
3580 enum attr_valloc valloc_method
;
3582 for (insn
= get_insns (); insn
; insn
= curr
)
3586 curr
= next_nonnote_nondebug_insn (insn
);
3589 && (GET_CODE (PATTERN (insn
)) == SET
3590 || GET_CODE (PATTERN (insn
)) == CALL
)
3591 && INSN_CODE (insn
) == -1)
3593 if (GET_CODE (SET_SRC (PATTERN (insn
))) == ASM_OPERANDS
)
3595 i
= recog (PATTERN (insn
), insn
, 0);
3601 INSN_CODE (insn
) = i
;
3605 cfun
->machine
->virt_insns_ok
= 0;
3606 cfun
->machine
->real_insns_ok
= 1;
3608 clear_content_memory ();
3610 for (insn
= get_insns (); insn
; insn
= curr
)
3614 curr
= insn
? next_nonnote_nondebug_insn (insn
) : NULL
;
3619 clear_content_memory ();
3625 fprintf (dump_file
, "Converting insn %d\n", INSN_UID (insn
));
3627 pattern
= PATTERN (insn
);
3628 if (GET_CODE (pattern
) == PARALLEL
)
3629 pattern
= XVECEXP (pattern
, 0, 0);
3630 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3631 clear_content_memory ();
3632 if (GET_CODE (pattern
) != SET
3633 && GET_CODE (pattern
) != CALL
)
3635 if (GET_CODE (pattern
) == SET
3636 && GET_CODE (SET_SRC (pattern
)) == ASM_OPERANDS
)
3639 valloc_method
= get_attr_valloc (insn
);
3641 PATTERN (insn
) = copy_rtx_if_shared (PATTERN (insn
));
3643 if (valloc_method
== VALLOC_MACAX
)
3645 record_content (AX
, NULL_RTX
);
3646 record_content (BC
, NULL_RTX
);
3647 record_content (DE
, NULL_RTX
);
3649 else if (valloc_method
== VALLOC_DIVHI
)
3651 record_content (AX
, NULL_RTX
);
3652 record_content (BC
, NULL_RTX
);
3654 else if (valloc_method
== VALLOC_DIVSI
)
3656 record_content (AX
, NULL_RTX
);
3657 record_content (BC
, NULL_RTX
);
3658 record_content (DE
, NULL_RTX
);
3659 record_content (HL
, NULL_RTX
);
3662 if (insn_ok_now (insn
))
3665 INSN_CODE (insn
) = -1;
3667 if (RTX_FRAME_RELATED_P (insn
))
3668 virt_insn_was_frame
= 1;
3670 virt_insn_was_frame
= 0;
3672 switch (valloc_method
)
3675 rl78_alloc_physical_registers_op1 (insn
);
3678 rl78_alloc_physical_registers_op2 (insn
);
3681 rl78_alloc_physical_registers_ro1 (insn
);
3684 rl78_alloc_physical_registers_cmp (insn
);
3687 rl78_alloc_physical_registers_umul (insn
);
3688 record_content (AX
, NULL_RTX
);
3691 /* Macro that clobbers AX. */
3692 rl78_alloc_address_registers_macax (insn
);
3693 record_content (AX
, NULL_RTX
);
3694 record_content (BC
, NULL_RTX
);
3695 record_content (DE
, NULL_RTX
);
3698 rl78_alloc_address_registers_div (insn
);
3699 record_content (AX
, NULL_RTX
);
3700 record_content (BC
, NULL_RTX
);
3701 record_content (DE
, NULL_RTX
);
3702 record_content (HL
, NULL_RTX
);
3705 rl78_alloc_address_registers_div (insn
);
3706 record_content (AX
, NULL_RTX
);
3707 record_content (BC
, NULL_RTX
);
3713 if (JUMP_P (insn
) || CALL_P (insn
) || GET_CODE (pattern
) == CALL
)
3714 clear_content_memory ();
3716 process_postponed_content_update ();
3720 fprintf (stderr
, "\033[0m");
3724 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
3725 This function scans for uses of registers; the last use (i.e. first
3726 encounter when scanning backwards) triggers a REG_DEAD note if the
3727 reg was previously in DEAD[]. */
3729 rl78_note_reg_uses (char *dead
, rtx s
, rtx insn
)
3738 code
= GET_CODE (s
);
3742 /* Compare registers by number. */
3747 fprintf (dump_file
, "note use reg %d size %d on insn %d\n",
3748 r
, GET_MODE_SIZE (GET_MODE (s
)), INSN_UID (insn
));
3749 print_rtl_single (dump_file
, s
);
3752 add_reg_note (insn
, REG_DEAD
, gen_rtx_REG (GET_MODE (s
), r
));
3753 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (s
)); i
++)
3757 /* These codes have no constituent expressions
3768 /* These are kept unique for a given value. */
3775 fmt
= GET_RTX_FORMAT (code
);
3777 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
3782 for (j
= XVECLEN (s
, i
) - 1; j
>= 0; j
--)
3783 rl78_note_reg_uses (dead
, XVECEXP (s
, i
, j
), insn
);
3785 else if (fmt
[i
] == 'e')
3786 rl78_note_reg_uses (dead
, XEXP (s
, i
), insn
);
3790 /* Like the previous function, but scan for SETs instead. */
3792 rl78_note_reg_set (char *dead
, rtx d
, rtx insn
)
3796 if (GET_CODE (d
) == MEM
)
3797 rl78_note_reg_uses (dead
, XEXP (d
, 0), insn
);
3799 if (GET_CODE (d
) != REG
)
3802 /* Do not mark the reg unused unless all QImode parts of it are dead. */
3805 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3809 add_reg_note (insn
, REG_UNUSED
, gen_rtx_REG (GET_MODE (d
), r
));
3811 fprintf (dump_file
, "note set reg %d size %d\n", r
, GET_MODE_SIZE (GET_MODE (d
)));
3812 for (i
= 0; i
< GET_MODE_SIZE (GET_MODE (d
)); i
++)
3816 /* This is a rather crude register death pass. Death status is reset
3817 at every jump or call insn. */
3819 rl78_calculate_death_notes (void)
3821 char dead
[FIRST_PSEUDO_REGISTER
];
3826 memset (dead
, 0, sizeof (dead
));
3828 for (insn
= get_last_insn ();
3830 insn
= prev_nonnote_nondebug_insn (insn
))
3834 fprintf (dump_file
, "\n--------------------------------------------------");
3835 fprintf (dump_file
, "\nDead:");
3836 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3838 fprintf (dump_file
, " %s", reg_names
[i
]);
3839 fprintf (dump_file
, "\n");
3840 print_rtl_single (dump_file
, insn
);
3843 switch (GET_CODE (insn
))
3847 if (GET_CODE (p
) == PARALLEL
)
3849 rtx q
= XVECEXP (p
, 0 ,1);
3851 /* This happens with the DIV patterns. */
3852 if (GET_CODE (q
) == SET
)
3856 rl78_note_reg_set (dead
, d
, insn
);
3857 rl78_note_reg_uses (dead
, s
, insn
);
3860 p
= XVECEXP (p
, 0, 0);
3863 switch (GET_CODE (p
))
3868 rl78_note_reg_set (dead
, d
, insn
);
3869 rl78_note_reg_uses (dead
, s
, insn
);
3873 rl78_note_reg_uses (dead
, p
, insn
);
3882 if (INSN_CODE (insn
) == CODE_FOR_rl78_return
)
3884 memset (dead
, 1, sizeof (dead
));
3885 /* We expect a USE just prior to this, which will mark
3886 the actual return registers. The USE will have a
3887 death note, but we aren't going to be modifying it
3893 memset (dead
, 0, sizeof (dead
));
3900 print_rtl_single (dump_file
, insn
);
3904 /* Helper function to reset the origins in RP and the age in AGE for
3907 reset_origins (int *rp
, int *age
)
3910 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
3918 set_origin (rtx pat
, rtx_insn
* insn
, int * origins
, int * age
)
3920 rtx src
= SET_SRC (pat
);
3921 rtx dest
= SET_DEST (pat
);
3922 int mb
= GET_MODE_SIZE (GET_MODE (dest
));
3925 if (GET_CODE (dest
) == REG
)
3927 int dr
= REGNO (dest
);
3929 if (GET_CODE (src
) == REG
)
3931 int sr
= REGNO (src
);
3933 int best_age
, best_reg
;
3935 /* See if the copy is not needed. */
3936 for (i
= 0; i
< mb
; i
++)
3937 if (origins
[dr
+ i
] != origins
[sr
+ i
])
3943 fprintf (dump_file
, "deleting because dest already has correct value\n");
3948 if (dr
< 8 || sr
>= 8)
3955 /* See if the copy can be made from another
3956 bank 0 register instead, instead of the
3957 virtual src register. */
3958 for (ar
= 0; ar
< 8; ar
+= mb
)
3962 for (i
= 0; i
< mb
; i
++)
3963 if (origins
[ar
+ i
] != origins
[sr
+ i
])
3966 /* The chip has some reg-reg move limitations. */
3967 if (mb
== 1 && dr
> 3)
3972 if (best_age
== -1 || best_age
> age
[sr
+ i
])
3974 best_age
= age
[sr
+ i
];
3982 /* FIXME: copy debug info too. */
3983 SET_SRC (pat
) = gen_rtx_REG (GET_MODE (src
), best_reg
);
3988 for (i
= 0; i
< mb
; i
++)
3990 origins
[dr
+ i
] = origins
[sr
+ i
];
3991 age
[dr
+ i
] = age
[sr
+ i
] + 1;
3996 /* The destination is computed, its origin is itself. */
3998 fprintf (dump_file
, "resetting origin of r%d for %d byte%s\n",
3999 dr
, mb
, mb
== 1 ? "" : "s");
4001 for (i
= 0; i
< mb
; i
++)
4003 origins
[dr
+ i
] = dr
+ i
;
4008 /* Any registers marked with that reg as an origin are reset. */
4009 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4010 if (origins
[i
] >= dr
&& origins
[i
] < dr
+ mb
)
4017 /* Special case - our MUL patterns uses AX and sometimes BC. */
4018 if (get_attr_valloc (insn
) == VALLOC_MACAX
)
4021 fprintf (dump_file
, "Resetting origin of AX/BC for MUL pattern.\n");
4023 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4024 if (i
<= 3 || origins
[i
] <= 3)
4030 else if (get_attr_valloc (insn
) == VALLOC_DIVHI
)
4033 fprintf (dump_file
, "Resetting origin of AX/DE for DIVHI pattern.\n");
4035 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4040 || origins
[i
] == A_REG
4041 || origins
[i
] == X_REG
4042 || origins
[i
] == D_REG
4043 || origins
[i
] == E_REG
)
4049 else if (get_attr_valloc (insn
) == VALLOC_DIVSI
)
4052 fprintf (dump_file
, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
4054 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4055 if (i
<= 7 || origins
[i
] <= 7)
4062 if (GET_CODE (src
) == ASHIFT
4063 || GET_CODE (src
) == ASHIFTRT
4064 || GET_CODE (src
) == LSHIFTRT
)
4066 rtx count
= XEXP (src
, 1);
4068 if (GET_CODE (count
) == REG
)
4070 /* Special case - our pattern clobbers the count register. */
4071 int r
= REGNO (count
);
4074 fprintf (dump_file
, "Resetting origin of r%d for shift.\n", r
);
4076 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4077 if (i
== r
|| origins
[i
] == r
)
4086 /* The idea behind this optimization is to look for cases where we
4087 move data from A to B to C, and instead move from A to B, and A to
4088 C. If B is a virtual register or memory, this is a big win on its
4089 own. If B turns out to be unneeded after this, it's a bigger win.
4090 For each register, we try to determine where it's value originally
4091 came from, if it's propogated purely through moves (and not
4092 computes). The ORIGINS[] array has the regno for the "origin" of
4093 the value in the [regno] it's indexed by. */
4095 rl78_propogate_register_origins (void)
4097 int origins
[FIRST_PSEUDO_REGISTER
];
4098 int age
[FIRST_PSEUDO_REGISTER
];
4100 rtx_insn
*insn
, *ninsn
= NULL
;
4103 reset_origins (origins
, age
);
4105 for (insn
= get_insns (); insn
; insn
= ninsn
)
4107 ninsn
= next_nonnote_nondebug_insn (insn
);
4111 fprintf (dump_file
, "\n");
4112 fprintf (dump_file
, "Origins:");
4113 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
4114 if (origins
[i
] != i
)
4115 fprintf (dump_file
, " r%d=r%d", i
, origins
[i
]);
4116 fprintf (dump_file
, "\n");
4117 print_rtl_single (dump_file
, insn
);
4120 switch (GET_CODE (insn
))
4126 reset_origins (origins
, age
);
4133 pat
= PATTERN (insn
);
4135 if (GET_CODE (pat
) == PARALLEL
)
4137 rtx clobber
= XVECEXP (pat
, 0, 1);
4138 pat
= XVECEXP (pat
, 0, 0);
4139 if (GET_CODE (clobber
) == CLOBBER
4140 && GET_CODE (XEXP (clobber
, 0)) == REG
)
4142 int cr
= REGNO (XEXP (clobber
, 0));
4143 int mb
= GET_MODE_SIZE (GET_MODE (XEXP (clobber
, 0)));
4145 fprintf (dump_file
, "reset origins of %d regs at %d\n", mb
, cr
);
4146 for (i
= 0; i
< mb
; i
++)
4148 origins
[cr
+ i
] = cr
+ i
;
4152 /* This happens with the DIV patterns. */
4153 else if (GET_CODE (clobber
) == SET
)
4155 set_origin (clobber
, insn
, origins
, age
);
4161 if (GET_CODE (pat
) == SET
)
4163 set_origin (pat
, insn
, origins
, age
);
4165 else if (GET_CODE (pat
) == CLOBBER
4166 && GET_CODE (XEXP (pat
, 0)) == REG
)
4168 if (REG_P (XEXP (pat
, 0)))
4170 unsigned int reg
= REGNO (XEXP (pat
, 0));
4180 /* Remove any SETs where the destination is unneeded. */
4182 rl78_remove_unused_sets (void)
4184 rtx_insn
*insn
, *ninsn
= NULL
;
4187 for (insn
= get_insns (); insn
; insn
= ninsn
)
4189 ninsn
= next_nonnote_nondebug_insn (insn
);
4191 rtx set
= single_set (insn
);
4195 dest
= SET_DEST (set
);
4197 if (GET_CODE (dest
) != REG
|| REGNO (dest
) > 23)
4200 if (find_regno_note (insn
, REG_UNUSED
, REGNO (dest
)))
4203 fprintf (dump_file
, "deleting because the set register is never used.\n");
4209 /* This is the top of the devritualization pass. */
4213 /* split2 only happens when optimizing, but we need all movSIs to be
4218 rl78_alloc_physical_registers ();
4222 fprintf (dump_file
, "\n================DEVIRT:=AFTER=ALLOC=PHYSICAL=REGISTERS================\n");
4223 print_rtl_with_bb (dump_file
, get_insns (), 0);
4226 rl78_propogate_register_origins ();
4227 rl78_calculate_death_notes ();
4231 fprintf (dump_file
, "\n================DEVIRT:=AFTER=PROPOGATION=============================\n");
4232 print_rtl_with_bb (dump_file
, get_insns (), 0);
4233 fprintf (dump_file
, "\n======================================================================\n");
4236 rl78_remove_unused_sets ();
4238 /* The code after devirtualizing has changed so much that at this point
4239 we might as well just rescan everything. Note that
4240 df_rescan_all_insns is not going to help here because it does not
4241 touch the artificial uses and defs. */
4242 df_finish_pass (true);
4244 df_live_add_problem ();
4245 df_scan_alloc (NULL
);
4252 #undef TARGET_RETURN_IN_MEMORY
4253 #define TARGET_RETURN_IN_MEMORY rl78_return_in_memory
4256 rl78_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
4258 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
4259 return (size
== -1 || size
> 8);
4263 #undef TARGET_RTX_COSTS
4264 #define TARGET_RTX_COSTS rl78_rtx_costs
4267 rl78_rtx_costs (rtx x
,
4269 int outer_code ATTRIBUTE_UNUSED
,
4270 int opno ATTRIBUTE_UNUSED
,
4272 bool speed ATTRIBUTE_UNUSED
)
4274 int code
= GET_CODE (x
);
4276 if (code
== IF_THEN_ELSE
)
4278 *total
= COSTS_N_INSNS (10);
4284 if (code
== MULT
&& ! speed
)
4286 * total
= COSTS_N_INSNS (8);
4298 /* If we are compiling for space then we do not want to use the
4299 inline SImode multiplication patterns or shift sequences.
4300 The cost is not set to 1 or 5 however as we have to allow for
4301 the possibility that we might be converting a leaf function
4302 into a non-leaf function. (There is no way to tell here).
4303 A value of 13 seems to be a reasonable compromise for the
4305 * total
= COSTS_N_INSNS (13);
4306 else if (RL78_MUL_G14
)
4307 *total
= COSTS_N_INSNS (14);
4308 else if (RL78_MUL_G13
)
4309 *total
= COSTS_N_INSNS (29);
4311 *total
= COSTS_N_INSNS (500);
4315 *total
= COSTS_N_INSNS (8);
4321 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4323 switch (INTVAL (XEXP (x
, 1)))
4325 case 0: *total
= COSTS_N_INSNS (0); break;
4326 case 1: *total
= COSTS_N_INSNS (6); break;
4327 case 2: case 3: case 4: case 5: case 6: case 7:
4328 *total
= COSTS_N_INSNS (10); break;
4329 case 8: *total
= COSTS_N_INSNS (6); break;
4330 case 9: case 10: case 11: case 12: case 13: case 14: case 15:
4331 *total
= COSTS_N_INSNS (10); break;
4332 case 16: *total
= COSTS_N_INSNS (3); break;
4333 case 17: case 18: case 19: case 20: case 21: case 22: case 23:
4334 *total
= COSTS_N_INSNS (4); break;
4335 case 24: *total
= COSTS_N_INSNS (4); break;
4336 case 25: case 26: case 27: case 28: case 29: case 30: case 31:
4337 *total
= COSTS_N_INSNS (5); break;
4341 *total
= COSTS_N_INSNS (10+4*16);
4352 static GTY(()) section
* saddr_section
;
4353 static GTY(()) section
* frodata_section
;
4356 rl78_saddr_p (rtx x
)
4362 if (GET_CODE (x
) == PLUS
)
4364 if (GET_CODE (x
) != SYMBOL_REF
)
4368 if (memcmp (c
, "@s.", 3) == 0)
4379 if (GET_CODE (x
) != CONST_INT
)
4382 if ((INTVAL (x
) & 0xFF00) != 0xFF00)
4388 #undef TARGET_STRIP_NAME_ENCODING
4389 #define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding
4392 rl78_strip_name_encoding (const char * sym
)
4398 else if (*sym
== '@' && sym
[2] == '.')
4405 /* Like rl78_strip_name_encoding, but does not strip leading asterisks. This
4406 is important if the stripped name is going to be passed to assemble_name()
4407 as that handles asterisk prefixed names in a special manner. */
4410 rl78_strip_nonasm_name_encoding (const char * sym
)
4414 if (*sym
== '@' && sym
[2] == '.')
4423 rl78_attrlist_to_encoding (tree list
, tree decl ATTRIBUTE_UNUSED
)
4427 if (is_attribute_p ("saddr", TREE_PURPOSE (list
)))
4429 list
= TREE_CHAIN (list
);
4435 #define RL78_ATTRIBUTES(decl) \
4436 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
4437 : DECL_ATTRIBUTES (decl) \
4438 ? (DECL_ATTRIBUTES (decl)) \
4439 : TYPE_ATTRIBUTES (TREE_TYPE (decl))
4441 #undef TARGET_ENCODE_SECTION_INFO
4442 #define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info
4445 rl78_encode_section_info (tree decl
, rtx rtl
, int first
)
4448 const char * oldname
;
4453 tree rl78_attributes
;
4458 rtlname
= XEXP (rtl
, 0);
4460 if (GET_CODE (rtlname
) == SYMBOL_REF
)
4461 oldname
= XSTR (rtlname
, 0);
4462 else if (GET_CODE (rtlname
) == MEM
4463 && GET_CODE (XEXP (rtlname
, 0)) == SYMBOL_REF
)
4464 oldname
= XSTR (XEXP (rtlname
, 0), 0);
4468 type
= TREE_TYPE (decl
);
4469 if (type
== error_mark_node
)
4471 if (! DECL_P (decl
))
4473 rl78_attributes
= RL78_ATTRIBUTES (decl
);
4475 encoding
= rl78_attrlist_to_encoding (rl78_attributes
, decl
);
4479 newname
= (char *) alloca (strlen (oldname
) + 4);
4480 sprintf (newname
, "@%c.%s", encoding
, oldname
);
4481 idp
= get_identifier (newname
);
4483 gen_rtx_SYMBOL_REF (Pmode
, IDENTIFIER_POINTER (idp
));
4484 SYMBOL_REF_WEAK (XEXP (rtl
, 0)) = DECL_WEAK (decl
);
4485 SET_SYMBOL_REF_DECL (XEXP (rtl
, 0), decl
);
4489 #undef TARGET_ASM_INIT_SECTIONS
4490 #define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections
4493 rl78_asm_init_sections (void)
4496 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4497 "\t.section .saddr,\"aw\",@progbits");
4499 = get_unnamed_section (SECTION_WRITE
, output_section_asm_op
,
4500 "\t.section .frodata,\"aw\",@progbits");
4503 #undef TARGET_ASM_SELECT_SECTION
4504 #define TARGET_ASM_SELECT_SECTION rl78_select_section
4507 rl78_select_section (tree decl
,
4509 unsigned HOST_WIDE_INT align
)
4513 switch (TREE_CODE (decl
))
4516 if (!TREE_READONLY (decl
)
4517 || TREE_SIDE_EFFECTS (decl
)
4518 || !DECL_INITIAL (decl
)
4519 || (DECL_INITIAL (decl
) != error_mark_node
4520 && !TREE_CONSTANT (DECL_INITIAL (decl
))))
4524 if (! TREE_CONSTANT (decl
))
4532 if (TREE_CODE (decl
) == VAR_DECL
)
4534 const char *name
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
4536 if (name
[0] == '@' && name
[2] == '.')
4540 return saddr_section
;
4543 if (TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_FAR
4546 return frodata_section
;
4551 return TARGET_ES0
? frodata_section
: readonly_data_section
;
4553 switch (categorize_decl_for_section (decl
, reloc
))
4555 case SECCAT_TEXT
: return text_section
;
4556 case SECCAT_DATA
: return data_section
;
4557 case SECCAT_BSS
: return bss_section
;
4558 case SECCAT_RODATA
: return TARGET_ES0
? frodata_section
: readonly_data_section
;
4560 return default_select_section (decl
, reloc
, align
);
4565 rl78_output_labelref (FILE *file
, const char *str
)
4569 str2
= targetm
.strip_name_encoding (str
);
4571 fputs (user_label_prefix
, file
);
4576 rl78_output_aligned_common (FILE *stream
,
4577 tree decl ATTRIBUTE_UNUSED
,
4579 int size
, int align
, int global
)
4581 /* We intentionally don't use rl78_section_tag() here. */
4582 if (name
[0] == '@' && name
[2] == '.')
4584 const char *sec
= 0;
4588 switch_to_section (saddr_section
);
4597 while (align
> BITS_PER_UNIT
)
4602 name2
= targetm
.strip_name_encoding (name
);
4604 fprintf (stream
, "\t.global\t_%s\n", name2
);
4605 fprintf (stream
, "\t.p2align %d\n", p2align
);
4606 fprintf (stream
, "\t.type\t_%s,@object\n", name2
);
4607 fprintf (stream
, "\t.size\t_%s,%d\n", name2
, size
);
4608 fprintf (stream
, "_%s:\n\t.zero\t%d\n", name2
, size
);
4615 fprintf (stream
, "\t.local\t");
4616 assemble_name (stream
, name
);
4617 fprintf (stream
, "\n");
4619 fprintf (stream
, "\t.comm\t");
4620 assemble_name (stream
, name
);
4621 fprintf (stream
, ",%u,%u\n", size
, align
/ BITS_PER_UNIT
);
4624 #undef TARGET_INSERT_ATTRIBUTES
4625 #define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes
4628 rl78_insert_attributes (tree decl
, tree
*attributes ATTRIBUTE_UNUSED
)
4631 && TREE_CODE (decl
) == VAR_DECL
4632 && TREE_READONLY (decl
)
4633 && TREE_ADDRESSABLE (decl
)
4634 && TYPE_ADDR_SPACE (TREE_TYPE (decl
)) == ADDR_SPACE_GENERIC
)
4636 tree type
= TREE_TYPE (decl
);
4637 tree attr
= TYPE_ATTRIBUTES (type
);
4638 int q
= TYPE_QUALS_NO_ADDR_SPACE (type
) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR
);
4640 TREE_TYPE (decl
) = build_type_attribute_qual_variant (type
, attr
, q
);
4644 #undef TARGET_ASM_INTEGER
4645 #define TARGET_ASM_INTEGER rl78_asm_out_integer
4648 rl78_asm_out_integer (rtx x
, unsigned int size
, int aligned_p
)
4650 if (default_assemble_integer (x
, size
, aligned_p
))
4655 assemble_integer_with_op (".long\t", x
);
4662 #undef TARGET_UNWIND_WORD_MODE
4663 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
4665 static scalar_int_mode
4666 rl78_unwind_word_mode (void)
4671 #ifndef USE_COLLECT2
4672 #undef TARGET_ASM_CONSTRUCTOR
4673 #define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor
4674 #undef TARGET_ASM_DESTRUCTOR
4675 #define TARGET_ASM_DESTRUCTOR rl78_asm_destructor
4678 rl78_asm_ctor_dtor (rtx symbol
, int priority
, bool is_ctor
)
4682 if (priority
!= DEFAULT_INIT_PRIORITY
)
4684 /* This section of the function is based upon code copied
4685 from: gcc/varasm.c:get_cdtor_priority_section(). */
4688 sprintf (buf
, "%s.%.5u", is_ctor
? ".ctors" : ".dtors",
4689 MAX_INIT_PRIORITY
- priority
);
4690 sec
= get_section (buf
, 0, NULL
);
4693 sec
= is_ctor
? ctors_section
: dtors_section
;
4695 assemble_addr_to_section (symbol
, sec
);
4699 rl78_asm_constructor (rtx symbol
, int priority
)
4701 rl78_asm_ctor_dtor (symbol
, priority
, true);
4705 rl78_asm_destructor (rtx symbol
, int priority
)
4707 rl78_asm_ctor_dtor (symbol
, priority
, false);
4709 #endif /* ! USE_COLLECT2 */
4711 /* Scan backwards through the insn chain looking to see if the flags
4712 have been set for a comparison of OP against OPERAND. Start with
4713 the insn *before* the current insn. */
4716 rl78_flags_already_set (rtx op
, rtx operand
)
4718 /* We only track the Z flag. */
4719 if (GET_CODE (op
) != EQ
&& GET_CODE (op
) != NE
)
4722 /* This should not happen, but let's be paranoid. */
4723 if (current_output_insn
== NULL_RTX
)
4729 for (insn
= prev_nonnote_nondebug_insn (current_output_insn
);
4731 insn
= prev_nonnote_nondebug_insn (insn
))
4736 if (! INSN_P (insn
))
4739 /* Make sure that the insn can be recognized. */
4740 if (recog_memoized (insn
) == -1)
4743 enum attr_update_Z updated
= get_attr_update_Z (insn
);
4745 rtx set
= single_set (insn
);
4746 bool must_break
= (set
!= NULL_RTX
&& rtx_equal_p (operand
, SET_DEST (set
)));
4752 case UPDATE_Z_CLOBBER
:
4755 case UPDATE_Z_UPDATE_Z
:
4767 /* We have to re-recognize the current insn as the call(s) to
4768 get_attr_update_Z() above will have overwritten the recog_data cache. */
4769 recog_memoized (current_output_insn
);
4770 cleanup_subreg_operands (current_output_insn
);
4771 constrain_operands_cached (current_output_insn
, 1);
4777 rl78_addsi3_internal (rtx
* operands
, unsigned int alternative
)
4779 /* If we are adding in a constant symbolic address when -mes0
4780 is active then we know that the address must be <64K and
4781 that it is invalid to access anything above 64K relative to
4782 this address. So we can skip adding in the high bytes. */
4784 && GET_CODE (operands
[2]) == SYMBOL_REF
4785 && TREE_CODE (SYMBOL_REF_DECL (operands
[2])) == VAR_DECL
4786 && TREE_READONLY (SYMBOL_REF_DECL (operands
[2]))
4787 && ! TREE_SIDE_EFFECTS (SYMBOL_REF_DECL (operands
[2])))
4788 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax";
4790 switch (alternative
)
4794 return "movw ax, %h1\n\taddw ax, %h2\n\tmovw %h0, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax";
4796 return "movw ax, %h1\n\taddw ax,%h2\n\tmovw bc, ax\n\tmovw ax, %H1\n\tsknc\n\tincw ax\n\taddw ax, %H2\n\tmovw %H0, ax\n\tmovw ax, bc\n\tmovw %h0, ax";
4803 rl78_emit_libcall (const char *name
, enum rtx_code code
,
4804 enum machine_mode dmode
, enum machine_mode smode
,
4805 int noperands
, rtx
*operands
)
4813 libcall
= gen_rtx_SYMBOL_REF (Pmode
, name
);
4818 ret
= emit_library_call_value (libcall
, NULL_RTX
, LCT_CONST
,
4819 dmode
, operands
[1], smode
);
4820 equiv
= gen_rtx_fmt_e (code
, dmode
, operands
[1]);
4824 ret
= emit_library_call_value (libcall
, NULL_RTX
,
4826 operands
[1], smode
, operands
[2],
4828 equiv
= gen_rtx_fmt_ee (code
, dmode
, operands
[1], operands
[2]);
4835 insns
= get_insns ();
4837 emit_libcall_block (insns
, operands
[0], ret
, equiv
);
4842 #undef TARGET_PREFERRED_RELOAD_CLASS
4843 #define TARGET_PREFERRED_RELOAD_CLASS rl78_preferred_reload_class
4846 rl78_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t rclass
)
4848 if (rclass
== NO_REGS
)
4855 struct gcc_target targetm
= TARGET_INITIALIZER
;
4857 #include "gt-rl78.h"