diff options
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/rl78/rl78.c | 88 | ||||
-rw-r--r-- | gcc/config/rl78/rl78.md | 10 | ||||
-rw-r--r-- | gcc/config/rl78/rl78.opt | 4 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 16 |
5 files changed, 129 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad4f9f7bcff..1adf8b51ee9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 13c22539268..2d850610ea6 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -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 diff --git a/gcc/config/rl78/rl78.md b/gcc/config/rl78/rl78.md index 739f6057b92..33bd1988537 100644 --- a/gcc/config/rl78/rl78.md +++ b/gcc/config/rl78/rl78.md @@ -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")] ) diff --git a/gcc/config/rl78/rl78.opt b/gcc/config/rl78/rl78.opt index a8e53ee0735..26db67cb658 100644 --- a/gcc/config/rl78/rl78.opt +++ b/gcc/config/rl78/rl78.opt @@ -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. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 05542492dab..908dbe856ee 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 |