rl78.c (rl78_expand_prologue): Save the MDUC related registers in all interrupt handl...
authorKaushik Phatak <kaushik.phatak@kpit.com>
Mon, 9 May 2016 11:44:58 +0000 (11:44 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Mon, 9 May 2016 11:44:58 +0000 (11:44 +0000)
* 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

gcc/ChangeLog
gcc/config/rl78/rl78.c
gcc/config/rl78/rl78.md
gcc/config/rl78/rl78.opt
gcc/doc/invoke.texi

index ad4f9f7bcffa5b78a998f43c8ab3279df4e7d71f..1adf8b51ee93b746a53b8ef52d0daf9a2fe1016c 100644 (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.
index 13c2253926867f15c52c11ac935152fa66ae46f1..2d850610ea609cb546ee509e949f240a397628ce 100644 (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
index 739f6057b922161e17d1aa2a6d97bb1543264882..33bd198853750e013712cf42b4e1eb930a9fee80 100644 (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
 
        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
        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"
        movw    %H3, ax         \n\
        ; end of udivmodsi macro";
       }
-  [(set_attr "valloc" "macax")]
+  [(set_attr "valloc" "macax")
+   (set_attr "is_g13_muldiv_insn" "yes")]
 )
index a8e53ee0735fb271933dce16cebb12615d6fc74b..26db67cb6587803763fb0da1e4fe80fb501e9e5e 100644 (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.
index 05542492dabfd545733a55b39260658600962772..908dbe856eed559813aa839667649ee83a5a4229 100644 (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