This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[m32c] add bank_switch and fast_interrupt attributes


Committed.

	* config/m32c/m32c.md (UNS_FSETB, UNS_FREIT): New.
	* config/m32c/prologue.md (epilogue_freit): New.
	(fset_b): New.
	* config/m32c/m32c.c (m32c_function_needs_enter): Add prototype.
	(bank_switch_p): Likewise.
	(fast_interrupt_p): Likewise.
	(interrupt_p): Likewise.
	(m32c_conditional_register_usage): Round memregs size up.
	(need_to_save): We only need to save $a0 when we use ENTER.
	(interrupt_p): Check for fast_interrupt too.
	(bank_switch_p): New.
	(fast_interrupt_p): New.
	(m32c_attribute_table): Add bank_switch and fast_interrupt.
	(m32c_emit_prolog): Support bank switching and fast interrupts.
	* doc/extend.texi (Function Attributes): Add bank_switch and
	fast_interrupt.


Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 150861)
+++ doc/extend.texi	(working copy)
@@ -2016,12 +2016,18 @@ behavior.
 This attribute is useful for small inline wrappers which if possible
 should appear during debugging as a unit, depending on the debug
 info format it will either mean marking the function as artificial
 or using the caller location for all instructions within the inlined
 body.
 
+@item bank_switch
+@cindex interrupt handler functions
+When added to an interrupt handler with the M32C port, causes the
+prologue and epilogue to use bank switching to preserve the registers
+rather than saving them on the stack.
+
 @item flatten
 @cindex @code{flatten} function attribute
 Generally, inlining into a function is limited.  For a function marked with
 this attribute, every call inside this function will be inlined, if possible.
 Whether the function itself is considered for inlining depends on its size and
 the current inlining parameters.
@@ -2269,12 +2275,19 @@ instead of using @code{rts}.  The board-
 the @code{rtc}.
 
 On MeP targets this causes the compiler to use a calling convention
 which assumes the called function is too far away for the built-in
 addressing modes.
 
+@item fast_interrupt
+@cindex interrupt handler functions
+Use this attribute on the M32C port to indicate that the specified
+function is a fast interrupt handler.  This is just like the
+@code{interrupt} attribute, except that @code{freit} is used to return
+instead of @code{reit}.
+
 @item fastcall
 @cindex functions that pop the argument stack on the 386
 On the Intel 386, the @code{fastcall} attribute causes the compiler to
 pass the first argument (if of integral type) in the register ECX and
 the second argument (if of integral type) in the register EDX@.  Subsequent
 and other typed arguments are passed on the stack.  The called function will
Index: config/m32c/m32c.c
===================================================================
--- config/m32c/m32c.c	(revision 150861)
+++ config/m32c/m32c.c	(working copy)
@@ -57,15 +57,19 @@ typedef enum
 {
   PP_pushm,
   PP_popm,
   PP_justcount
 } Push_Pop_Type;
 
+static bool m32c_function_needs_enter (void);
 static tree interrupt_handler (tree *, tree, tree, int, bool *);
 static tree function_vector_handler (tree *, tree, tree, int, bool *);
 static int interrupt_p (tree node);
+static int bank_switch_p (tree node);
+static int fast_interrupt_p (tree node);
+static int interrupt_p (tree node);
 static bool m32c_asm_integer (rtx, unsigned int, int);
 static int m32c_comp_type_attributes (const_tree, const_tree);
 static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static struct machine_function *m32c_init_machine_status (void);
 static void m32c_insert_attributes (tree, tree *);
 static bool m32c_legitimate_address_p (enum machine_mode, rtx, bool);
@@ -490,13 +494,13 @@ m32c_conditional_register_usage (void)
   int i;
 
   if (0 <= target_memregs && target_memregs <= 16)
     {
       /* The command line option is bytes, but our "registers" are
 	 16-bit words.  */
-      for (i = target_memregs/2; i < 8; i++)
+      for (i = (target_memregs+1)/2; i < 8; i++)
 	{
 	  fixed_regs[MEM0_REGNO + i] = 1;
 	  CLEAR_HARD_REG_BIT (reg_class_contents[MEM_REGS], MEM0_REGNO + i);
 	}
     }
 
@@ -1252,13 +1256,16 @@ need_to_save (int regno)
     return 0;
   if (crtl->calls_eh_return)
     return 1;
   if (regno == FP_REGNO)
     return 0;
   if (cfun->machine->is_interrupt
-      && (!cfun->machine->is_leaf || regno == A0_REGNO))
+      && (!cfun->machine->is_leaf
+	  || (regno == A0_REGNO
+	      && m32c_function_needs_enter ())
+	  ))
     return 1;
   if (df_regs_ever_live_p (regno)
       && (!call_used_regs[regno] || cfun->machine->is_interrupt))
     return 1;
   return 0;
 }
@@ -2730,12 +2737,40 @@ interrupt_p (tree node ATTRIBUTE_UNUSED)
   while (list)
     {
       if (is_attribute_p ("interrupt", TREE_PURPOSE (list)))
 	return 1;
       list = TREE_CHAIN (list);
     }
+  return fast_interrupt_p (node);
+}
+
+/* Returns TRUE if the given tree has the "bank_switch" attribute.  */
+static int
+bank_switch_p (tree node ATTRIBUTE_UNUSED)
+{
+  tree list = M32C_ATTRIBUTES (node);
+  while (list)
+    {
+      if (is_attribute_p ("bank_switch", TREE_PURPOSE (list)))
+	return 1;
+      list = TREE_CHAIN (list);
+    }
+  return 0;
+}
+
+/* Returns TRUE if the given tree has the "fast_interrupt" attribute.  */
+static int
+fast_interrupt_p (tree node ATTRIBUTE_UNUSED)
+{
+  tree list = M32C_ATTRIBUTES (node);
+  while (list)
+    {
+      if (is_attribute_p ("fast_interrupt", TREE_PURPOSE (list)))
+	return 1;
+      list = TREE_CHAIN (list);
+    }
   return 0;
 }
 
 static tree
 interrupt_handler (tree * node ATTRIBUTE_UNUSED,
 		   tree name ATTRIBUTE_UNUSED,
@@ -2843,12 +2878,14 @@ current_function_special_page_vector (rt
 }
 
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
 static const struct attribute_spec m32c_attribute_table[] = {
   {"interrupt", 0, 0, false, false, false, interrupt_handler},
+  {"bank_switch", 0, 0, false, false, false, interrupt_handler},
+  {"fast_interrupt", 0, 0, false, false, false, interrupt_handler},
   {"function_vector", 1, 1, true,  false, false, function_vector_handler},
   {0, 0, 0, 0, 0, 0, 0}
 };
 
 #undef TARGET_COMP_TYPE_ATTRIBUTES
 #define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
@@ -3925,22 +3962,29 @@ m32c_emit_prologue (void)
   cfun->machine->is_leaf = m32c_leaf_function_p ();
   if (interrupt_p (cfun->decl))
     {
       cfun->machine->is_interrupt = 1;
       complex_prologue = 1;
     }
+  else if (bank_switch_p (cfun->decl))
+    warning (OPT_Wattributes,
+	     "%<bank_switch%> has no effect on non-interrupt functions");
 
   reg_save_size = m32c_pushm_popm (PP_justcount);
 
   if (interrupt_p (cfun->decl))
-    emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
+    {
+      if (bank_switch_p (cfun->decl))
+	emit_insn (gen_fset_b ());
+      else if (cfun->machine->intr_pushm)
+	emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
+    }
 
   frame_size =
     m32c_initial_elimination_offset (FB_REGNO, SP_REGNO) - reg_save_size;
   if (frame_size == 0
-      && !cfun->machine->is_interrupt
       && !m32c_function_needs_enter ())
     cfun->machine->use_rts = 1;
 
   if (frame_size > 254)
     {
       extra_frame_size = frame_size - 254;
@@ -3985,22 +4029,35 @@ m32c_emit_epilogue (void)
   m32c_pushm_popm (PP_popm);
 
   if (cfun->machine->is_interrupt)
     {
       enum machine_mode spmode = TARGET_A16 ? HImode : PSImode;
 
-      emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
-		      gen_rtx_REG (spmode, FP_REGNO));
-      emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
-		      gen_rtx_REG (spmode, A0_REGNO));
-      if (TARGET_A16)
-	emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
-      else
-	emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
-      emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
-      if (TARGET_A16)
+      /* REIT clears B flag and restores $fp for us, but we still
+	 have to fix up the stack.  USE_RTS just means we didn't
+	 emit ENTER.  */
+      if (!cfun->machine->use_rts)
+	{
+	  emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
+			  gen_rtx_REG (spmode, FP_REGNO));
+	  emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
+			  gen_rtx_REG (spmode, A0_REGNO));
+	  /* We can't just add this to the POPM because it would be in
+	     the wrong order, and wouldn't fix the stack if we're bank
+	     switching.  */
+	  if (TARGET_A16)
+	    emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
+	  else
+	    emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
+	}
+      if (!bank_switch_p (cfun->decl) && cfun->machine->intr_pushm)
+	emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
+
+      if (fast_interrupt_p (cfun->decl))
+	emit_jump_insn (gen_epilogue_freit ());
+      else if (TARGET_A16)
 	emit_jump_insn (gen_epilogue_reit_16 ());
       else
 	emit_jump_insn (gen_epilogue_reit_24 ());
     }
   else if (cfun->machine->use_rts)
     emit_jump_insn (gen_epilogue_rts ());
Index: config/m32c/prologue.md
===================================================================
--- config/m32c/prologue.md	(revision 150861)
+++ config/m32c/prologue.md	(working copy)
@@ -146,12 +146,21 @@
    ]
   "TARGET_A24"
   "reit"
   [(set_attr "flags" "x")]
   )
 
+(define_insn "epilogue_freit"
+  [(unspec [(const_int 0)] UNS_FREIT)
+   (return)
+   ]
+  ""
+  "freit"
+  [(set_attr "flags" "x")]
+  )
+
 (define_insn "epilogue_rts"
   [(return)
    ]
   ""
   "rts"
   [(set_attr "flags" "x")]
@@ -177,6 +186,14 @@
 (define_insn "popm"
   [(unspec [(match_operand 0 "const_int_operand" "i")] UNS_POPM)]
   ""
   "popm\t%p0"
   [(set_attr "flags" "n")]
   )
+
+(define_insn "fset_b"
+  [(unspec [(const_int 0)] UNS_FSETB)]
+  ""
+  "fset\tB"
+  [(set_attr "flags" "n")]
+  )
+
Index: config/m32c/m32c.md
===================================================================
--- config/m32c/m32c.md	(revision 150861)
+++ config/m32c/m32c.md	(working copy)
@@ -44,12 +44,14 @@
    (UNS_PUSHM 4)
    (UNS_POPM 5)
    (UNS_SMOVF 6)
    (UNS_SSTR 7)
    (UNS_SCMPU 8)
    (UNS_SMOVU 9)
+   (UNS_FSETB 10)
+   (UNS_FREIT 11)
    ])
 
 ;; n = no change, x = clobbered.  The first 16 values are chosen such
 ;; that the enum has one bit set for each flag.
 (define_attr "flags" "x,c,z,zc,s,sc,sz,szc,o,oc,oz,ozc,os,osc,osz,oszc,n" (const_string "n"))
 (define_asm_attributes [(set_attr "flags" "x")])


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]