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:
parent
18caa34eb2
commit
035b8879ac
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")]
|
||||
)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue