rl78.c (rl78_expand_prologue): Save the MDUC related registers in all interrupt handlers if necessary.

* config/rl78/rl78.c (rl78_expand_prologue): Save the MDUC related
	registers in all interrupt handlers if necessary.
	(rl78_option_override): Add warning.
	(MUST_SAVE_MDUC_REGISTERS): New macro.
	(rl78_expand_epilogue): Restore the MDUC registers if necessary.
	* config/rl78/rl78.c (check_mduc_usage): New function.
	(mduc_regs): New structure to hold MDUC register data.
	* config/rl78/rl78.md (is_g13_muldiv_insn): New attribute.
	(mulsi3_g13): Add is_g13_muldiv_insn attribute.
	(udivmodsi4_g13): Add is_g13_muldiv_insn attribute.
	(mulhi3_g13): Add is_g13_muldiv_insn attribute.
	* config/rl78/rl78.opt (msave-mduc-in-interrupts): New option.
	* doc/invoke.texi (RL78 Options): Add -msave-mduc-in-interrupts.

From-SVN: r236027
This commit is contained in:
Kaushik Phatak 2016-05-09 11:44:58 +00:00 committed by Nick Clifton
parent 18caa34eb2
commit 035b8879ac
5 changed files with 129 additions and 5 deletions

View File

@ -1,3 +1,19 @@
2016-05-09 Kaushik Phatak <kaushik.phatak@kpit.com>
* config/rl78/rl78.c (rl78_expand_prologue): Save the MDUC related
registers in all interrupt handlers if necessary.
(rl78_option_override): Add warning.
(MUST_SAVE_MDUC_REGISTERS): New macro.
(rl78_expand_epilogue): Restore the MDUC registers if necessary.
* config/rl78/rl78.c (check_mduc_usage): New function.
(mduc_regs): New structure to hold MDUC register data.
* config/rl78/rl78.md (is_g13_muldiv_insn): New attribute.
(mulsi3_g13): Add is_g13_muldiv_insn attribute.
(udivmodsi4_g13): Add is_g13_muldiv_insn attribute.
(mulhi3_g13): Add is_g13_muldiv_insn attribute.
* config/rl78/rl78.opt (msave-mduc-in-interrupts): New option.
* doc/invoke.texi (RL78 Options): Add -msave-mduc-in-interrupts.
2016-05-09 Bin Cheng <bin.cheng@arm.com>
* tree-if-conv.c (tree-ssa-loop.h): Include header file.

View File

@ -76,6 +76,23 @@ static const char * const word_regnames[] =
"sp", "ap", "psw", "es", "cs"
};
/* Structure for G13 MDUC registers. */
struct mduc_reg_type
{
unsigned int address;
enum machine_mode mode;
};
struct mduc_reg_type mduc_regs[] =
{
{0xf00e8, QImode},
{0xffff0, HImode},
{0xffff2, HImode},
{0xf2224, HImode},
{0xf00e0, HImode},
{0xf00e2, HImode}
};
struct GTY(()) machine_function
{
/* If set, the rest of the fields have been computed. */
@ -317,6 +334,10 @@ rl78_output_symbol_ref (FILE * file, rtx sym)
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE rl78_option_override
#define MUST_SAVE_MDUC_REGISTERS \
(TARGET_SAVE_MDUC_REGISTERS \
&& (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
static void
rl78_option_override (void)
{
@ -344,6 +365,9 @@ rl78_option_override (void)
/* Address spaces are currently only supported by C. */
error ("-mes0 can only be used with C");
if (TARGET_SAVE_MDUC_REGISTERS && !(TARGET_G13 || RL78_MUL_G13))
warning (0, "mduc registers only saved for G13 target");
switch (rl78_cpu_type)
{
case CPU_UNINIT:
@ -1257,13 +1281,34 @@ rl78_initial_elimination_offset (int from, int to)
return rv;
}
static int
static bool
rl78_is_naked_func (void)
{
return (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE);
}
/* Check if the block uses mul/div insns for G13 target. */
static bool
check_mduc_usage (void)
{
rtx_insn * insn;
basic_block bb;
FOR_EACH_BB_FN (bb, cfun)
{
FOR_BB_INSNS (bb, insn)
{
if (INSN_P (insn)
&& (get_attr_is_g13_muldiv_insn (insn) == IS_G13_MULDIV_INSN_YES))
return true;
}
}
return false;
}
/* Expand the function prologue (from the prologue pattern). */
void
rl78_expand_prologue (void)
{
@ -1278,6 +1323,9 @@ rl78_expand_prologue (void)
/* Always re-compute the frame info - the register usage may have changed. */
rl78_compute_frame_info ();
if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
cfun->machine->framesize += ARRAY_SIZE (mduc_regs) * 2;
if (flag_stack_usage_info)
current_function_static_stack_size = cfun->machine->framesize;
@ -1327,6 +1375,24 @@ rl78_expand_prologue (void)
F (emit_insn (gen_push (ax)));
}
/* Save MDUC registers inside interrupt routine. */
if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
{
for (int i = 0; i < ARRAY_SIZE (mduc_regs); i++)
{
mduc_reg_type *reg = mduc_regs + i;
rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
MEM_VOLATILE_P (mem_mduc) = 1;
if (reg->mode == QImode)
emit_insn (gen_movqi (gen_rtx_REG (QImode, A_REG), mem_mduc));
else
emit_insn (gen_movhi (gen_rtx_REG (HImode, AX_REG), mem_mduc));
emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG)));
}
}
if (frame_pointer_needed)
{
F (emit_move_insn (ax, sp));
@ -1400,6 +1466,23 @@ rl78_expand_epilogue (void)
}
}
/* Restore MDUC registers from interrupt routine. */
if (MUST_SAVE_MDUC_REGISTERS && (!crtl->is_leaf || check_mduc_usage ()))
{
for (int i = ARRAY_SIZE (mduc_regs) - 1; i >= 0; i--)
{
mduc_reg_type *reg = mduc_regs + i;
rtx mem_mduc = gen_rtx_MEM (reg->mode, GEN_INT (reg->address));
emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
MEM_VOLATILE_P (mem_mduc) = 1;
if (reg->mode == QImode)
emit_insn (gen_movqi (mem_mduc, gen_rtx_REG (QImode, A_REG)));
else
emit_insn (gen_movhi (mem_mduc, gen_rtx_REG (HImode, AX_REG)));
}
}
if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
{
emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
@ -1495,6 +1578,9 @@ rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
if (cfun->machine->uses_es)
fprintf (file, "\t; uses ES register\n");
if (MUST_SAVE_MDUC_REGISTERS)
fprintf (file, "\t; preserves MDUC registers\n");
}
/* Return an RTL describing where a function return value of type RET_TYPE

View File

@ -67,6 +67,7 @@
(include "rl78-virt.md")
(include "rl78-real.md")
(define_attr "is_g13_muldiv_insn" "yes,no" (const_string "no"))
;; Function Prologue/Epilogue Instructions
@ -379,7 +380,8 @@
movw ax, 0xffff6 ; MDBL
movw %h0, ax
; end of mulhi macro"
[(set_attr "valloc" "macax")]
[(set_attr "valloc" "macax")
(set_attr "is_g13_muldiv_insn" "yes")]
)
;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it
@ -459,7 +461,8 @@
movw ax, !0xf00e0 ; MDCL
movw %H0, ax
; end of mulsi macro"
[(set_attr "valloc" "macax")]
[(set_attr "valloc" "macax")
(set_attr "is_g13_muldiv_insn" "yes")]
)
(define_expand "udivmodhi4"
@ -692,5 +695,6 @@
movw %H3, ax \n\
; end of udivmodsi macro";
}
[(set_attr "valloc" "macax")]
[(set_attr "valloc" "macax")
(set_attr "is_g13_muldiv_insn" "yes")]
)

View File

@ -91,3 +91,7 @@ Alias for -mcpu=g14.
mes0
Target Mask(ES0)
Assume ES is zero throughout program execution, use ES: for read-only data.
msave-mduc-in-interrupts
Target Mask(SAVE_MDUC_REGISTERS)
Stores the MDUC registers in interrupt handlers for G13 target.

View File

@ -947,7 +947,7 @@ See RS/6000 and PowerPC Options.
@emph{RL78 Options}
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol
-mcpu=g10 -mcpu=g13 -mcpu=g14 -mg10 -mg13 -mg14 @gol
-m64bit-doubles -m32bit-doubles}
-m64bit-doubles -m32bit-doubles -msave-mduc-in-interrupts}
@emph{RS/6000 and PowerPC Options}
@gccoptlist{-mcpu=@var{cpu-type} @gol
@ -19783,6 +19783,20 @@ Make the @code{double} data type be 64 bits (@option{-m64bit-doubles})
or 32 bits (@option{-m32bit-doubles}) in size. The default is
@option{-m32bit-doubles}.
@item -msave-mduc-in-interrupts
@item -mno-save-mduc-in-interrupts
@opindex msave-mduc-in-interrupts
@opindex mno-save-mduc-in-interrupts
Specifies that interrupt handler functions should preserve the
MDUC registers. This is only necessary if normal code might use
the MDUC registers, for example because it performs multiplication
and division operations. The default is to ignore the MDUC registers
as this makes the interrupt handlers faster. The target option -mg13
needs to be passed for this to work as this feature is only available
on the G13 target (S2 core). The MDUC registers will only be saved
if the interrupt handler performs a multiplication or division
operation or it calls another function.
@end table
@node RS/6000 and PowerPC Options