diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 70c15568c7403ce5e9612ccfa97926542202a95e..f5ee6e68c990ebb83e881817b4079e5c37bd8104 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,33 @@
+2003-01-04  Kazu Hirata  <kazu@cs.umass.edu>
+
+	* config/h8300/h8300-protos.h: Add prototypes for
+	the new functions defined below.
+	* config/h8300/h8300.c (TARGET_ASM_FUNCTION_PROLOGUE): Do not
+	define.
+	(dosize): Emit RTL instead of assembly code.
+	(push): Likewise.
+	(pop): Likewise.
+	(h8300_output_function_prologue): Remove.
+	(h8300_expand_prologue): New.
+	(h8300_expand_epilogue): New.
+	(h8300_output_function_epilogue): Do only the reset of
+	pragma_saveall.
+	* config/h8300/h8300.md (push_h8300): New.
+	(push_h8300hs): Likewise.
+	(pop_h8300): Likewise.
+	(pop_h8300hs): Likewise.
+	(*stm_h8300s_2): Change the name to stm_h8300s_2.
+	(*stm_h8300s_3): Change the name to stm_h8300s_3.
+	(*stm_h8300s_4): Change the name to stm_h8300s_4.
+	(*ldm_h8300s_2): New.
+	(*ldm_h8300s_3): Likewise.
+	(*ldm_h8300s_4): Likewise.
+	(return): Likewise.
+	(*return_1): Likewise.
+	(prologue): Likewise.
+	(epilogue): Likewise.
+	(monitor_prologue): Likewise.
+
 2003-01-03  Dale Johannesen  <dalej@apple.com>
 
 	* config/darwin.h:  (EXTRA_SECTIONS):  Add machopic_symbol_stub1,
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 1ea1ab2664ae44f4fb052a0800bab652df74aed7..f5a59d4b1202f7f843aa43159ff58fd2d289a01a 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -90,6 +90,9 @@ extern int h8300_tiny_data_p PARAMS ((tree));
 #endif /* TREE_CODE */
 
 extern void h8300_init_once PARAMS ((void));
+extern int h8300_can_use_return_insn_p PARAMS ((void));
+extern void h8300_expand_prologue PARAMS ((void));
+extern void h8300_expand_epilogue PARAMS ((void));
 extern int h8300_current_function_interrupt_function_p PARAMS ((void));
 extern void asm_file_start PARAMS ((FILE *));
 extern void asm_file_end PARAMS ((FILE *));
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 5e4063cf53c551713e6fd020c6f8f94cb903e509..f8ec6822c3bb25159d2b958a48e569ccfdd7f889 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -50,18 +50,17 @@ static const char *byte_reg PARAMS ((rtx, int));
 static int h8300_interrupt_function_p PARAMS ((tree));
 static int h8300_monitor_function_p PARAMS ((tree));
 static int h8300_os_task_function_p PARAMS ((tree));
-static void dosize PARAMS ((FILE *, int, unsigned int));
+static void dosize PARAMS ((int, unsigned int));
 static int round_frame_size PARAMS ((int));
 static unsigned int compute_saved_regs PARAMS ((void));
-static void push PARAMS ((FILE *, int));
-static void pop PARAMS ((FILE *, int));
+static void push PARAMS ((int));
+static void pop PARAMS ((int));
 static const char *cond_string PARAMS ((enum rtx_code));
 static unsigned int h8300_asm_insn_count PARAMS ((const char *));
 const struct attribute_spec h8300_attribute_table[];
 static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree h8300_handle_tiny_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static void h8300_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static void h8300_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 static void h8300_insert_attributes PARAMS ((tree, tree *));
 #ifndef OBJECT_FORMAT_ELF
@@ -104,8 +103,6 @@ const char *h8_push_op, *h8_pop_op, *h8_mov_op;
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
 
-#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE h8300_output_function_prologue
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE h8300_output_function_epilogue
 #undef TARGET_ENCODE_SECTION_INFO
@@ -386,50 +383,32 @@ byte_reg (x, b)
    SIZE to adjust the stack pointer.  */
 
 static void
-dosize (file, sign, size)
-     FILE *file;
+dosize (sign, size)
      int sign;
      unsigned int size;
 {
-  /* On the H8/300H and H8S, for sizes <= 8 bytes, it is as good or
-     better to use adds/subs insns rather than add.l/sub.l with an
-     immediate value.
-
-     Also, on the H8/300, if we don't have a temporary to hold the
-     size of the frame in the prologue, we simply emit a sequence of
-     subs since this shouldn't happen often.  */
-  if ((TARGET_H8300 && size <= 4)
-      || ((TARGET_H8300H || TARGET_H8300S) && size <= 8)
-      || (TARGET_H8300 && h8300_current_function_interrupt_function_p ())
-      || (TARGET_H8300 && current_function_needs_context
-	  && sign < 0))
+  /* H8/300 cannot add/subtract a large constant with a single
+     instruction.  If a temporary register is available, load the
+     constant to it and then do the addition.  */
+  if (TARGET_H8300
+      && size > 4
+      && !h8300_current_function_interrupt_function_p ()
+      && !(current_function_needs_context && sign < 0))
     {
-      const char *op = (sign > 0) ? "add" : "sub";
-      unsigned int amount;
-
-      /* Try different amounts in descending order.  */
-      for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
-	   amount > 0;
-	   amount /= 2)
-	{
-	  char insn[100];
-
-	  sprintf (insn, "\t%ss\t#%d,%s\n", op, amount,
-		   TARGET_H8300 ? "r7" : "er7");
-	  for (; size >= amount; size -= amount)
-	    fputs (insn, file);
-	}
+      rtx new_sp;
+      rtx r3 = gen_rtx_REG (Pmode, 3);
+      emit_insn (gen_rtx_SET (Pmode, r3, GEN_INT (sign * size)));
+      new_sp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, r3);
+      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx, new_sp));
     }
   else
     {
-      if (TARGET_H8300)
-	{
-	  fprintf (file, "\tmov.w\t#%d,r3\n\tadd.w\tr3,r7\n", sign * size);
-	}
-      else
-	{
-	  fprintf (file, "\tadd.l\t#%d,er7\n", sign * size);
-	}
+      /* The stack adjustment made here is further optimized by the
+	 splitter.  In case of H8/300, the splitter always splits the
+	 addition emitted here to make the adjustment
+	 interrupt-safe.  */
+      rtx new_sp = plus_constant (stack_pointer_rtx, sign * size);
+      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx, new_sp));
     }
 }
 
@@ -466,30 +445,38 @@ compute_saved_regs ()
   return saved_regs;
 }
 
-/* Output assembly language code to push register RN.  */
+/* Emit an insn to push register RN.  */
 
 static void
-push (file, rn)
-     FILE *file;
+push (rn)
      int rn;
 {
+  rtx reg = gen_rtx_REG (word_mode, rn);
+  rtx x;
+
   if (TARGET_H8300)
-    fprintf (file, "\t%s\t%s,@-r7\n", h8_mov_op, h8_reg_names[rn]);
+    x = gen_push_h8300 (reg);
   else
-    fprintf (file, "\t%s\t%s,@-er7\n", h8_mov_op, h8_reg_names[rn]);
+    x = gen_push_h8300hs (reg);
+  x = emit_insn (x);
+  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0);
 }
 
-/* Output assembly language code to pop register RN.  */
+/* Emit an insn to pop register RN.  */
 
 static void
-pop (file, rn)
-     FILE *file;
+pop (rn)
      int rn;
 {
+  rtx reg = gen_rtx_REG (word_mode, rn);
+  rtx x;
+
   if (TARGET_H8300)
-    fprintf (file, "\t%s\t@r7+,%s\n", h8_mov_op, h8_reg_names[rn]);
+    x = gen_pop_h8300 (reg);
   else
-    fprintf (file, "\t%s\t@er7+,%s\n", h8_mov_op, h8_reg_names[rn]);
+    x = gen_pop_h8300hs (reg);
+  x = emit_insn (x);
+  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0);
 }
 
 /* This is what the stack looks like after the prolog of
@@ -510,14 +497,12 @@ pop (file, rn)
    <saved registers>	<- sp
 */
 
-/* Output assembly language code for the function prologue.  */
+/* Generate RTL code for the function prologue.  */
 
-static void
-h8300_output_function_prologue (file, size)
-     FILE *file;
-     HOST_WIDE_INT size;
+void
+h8300_expand_prologue ()
 {
-  int fsize = round_frame_size (size);
+  int fsize = round_frame_size (get_frame_size ());
   int regno;
   int saved_regs;
   int n_regs;
@@ -525,58 +510,23 @@ h8300_output_function_prologue (file, size)
   /* If the current function has the OS_Task attribute set, then
      we have a naked prologue.  */
   if (h8300_os_task_function_p (current_function_decl))
-    {
-      fprintf (file, ";OS_Task prologue\n");
-      return;
-    }
+    return;
 
   if (h8300_monitor_function_p (current_function_decl))
-    {
-      /* My understanding of monitor functions is they act just
-	 like interrupt functions, except the prologue must
-	 mask interrupts.  */
-      fprintf (file, ";monitor prologue\n");
-      if (TARGET_H8300)
-	{
-	  fprintf (file, "\tsubs\t#2,sp\n");
-	  push (file, 0);
-	  fprintf (file, "\tstc\tccr,r0l\n");
-	  fprintf (file, "\tmov.b\tr0l,@(2,sp)\n");
-	  pop (file, 0);
-	  fprintf (file, "\torc\t#128,ccr\n");
-	}
-      else if (TARGET_H8300H)
-	{
-	  push (file, 0);
-	  fprintf (file, "\tstc\tccr,r0l\n");
-	  fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");
-	  pop (file, 0);
-	  fprintf (file, "\torc\t#128,ccr\n");
-	}
-      else if (TARGET_H8300S)
-	{
-	  fprintf (file, "\tstc\texr,@-sp\n");
-	  push (file, 0);
-	  fprintf (file, "\tstc\tccr,r0l\n");
-	  fprintf (file, "\tmov.b\tr0l,@(6,sp)\n");
-	  pop (file, 0);
-	  fprintf (file, "\torc\t#128,ccr\n");
-	}
-      else
-	abort ();
-    }
+    /* My understanding of monitor functions is they act just like
+       interrupt functions, except the prologue must mask
+       interrupts.  */
+    emit_insn (gen_monitor_prologue ());
 
   if (frame_pointer_needed)
     {
       /* Push fp.  */
-      push (file, FRAME_POINTER_REGNUM);
-      fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,
-	       h8_reg_names[STACK_POINTER_REGNUM],
-	       h8_reg_names[FRAME_POINTER_REGNUM]);
+      push (FRAME_POINTER_REGNUM);
+      emit_insn (gen_rtx_SET (Pmode, frame_pointer_rtx, stack_pointer_rtx));
     }
 
   /* Leave room for locals.  */
-  dosize (file, -1, fsize);
+  dosize (-1, fsize);
 
   /* Push the rest of the registers in ascending order.  */
   saved_regs = compute_saved_regs ();
@@ -604,22 +554,22 @@ h8300_output_function_prologue (file, size)
 	  switch (n_regs)
 	    {
 	    case 1:
-	      push (file, regno);
+	      push (regno);
 	      break;
 	    case 2:
-	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",
-		       h8_reg_names[regno],
-		       h8_reg_names[regno + 1]);
+	      emit_insn (gen_stm_h8300s_2 (gen_rtx_REG (SImode, regno),
+					   gen_rtx_REG (SImode, regno + 1)));
 	      break;
 	    case 3:
-	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",
-		       h8_reg_names[regno],
-		       h8_reg_names[regno + 2]);
+	      emit_insn (gen_stm_h8300s_3 (gen_rtx_REG (SImode, regno),
+					   gen_rtx_REG (SImode, regno + 1),
+					   gen_rtx_REG (SImode, regno + 2)));
 	      break;
 	    case 4:
-	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",
-		       h8_reg_names[regno],
-		       h8_reg_names[regno + 3]);
+	      emit_insn (gen_stm_h8300s_4 (gen_rtx_REG (SImode, regno),
+					   gen_rtx_REG (SImode, regno + 1),
+					   gen_rtx_REG (SImode, regno + 2),
+					   gen_rtx_REG (SImode, regno + 3)));
 	      break;
 	    default:
 	      abort ();
@@ -628,38 +578,29 @@ h8300_output_function_prologue (file, size)
     }
 }
 
-/* Output assembly language code for the function epilogue.  */
+int
+h8300_can_use_return_insn_p ()
+{
+  return (reload_completed
+	  && !frame_pointer_needed
+	  && get_frame_size () == 0
+	  && compute_saved_regs () == 0);
+}
 
-static void
-h8300_output_function_epilogue (file, size)
-     FILE *file;
-     HOST_WIDE_INT size;
+/* Generate RTL code for the function epilogue.  */
+
+void
+h8300_expand_epilogue ()
 {
-  int fsize = round_frame_size (size);
+  int fsize = round_frame_size (get_frame_size ());
   int regno;
-  rtx insn = get_last_insn ();
   int saved_regs;
   int n_regs;
 
   if (h8300_os_task_function_p (current_function_decl))
-    {
-      /* OS_Task epilogues are nearly naked -- they just have an
-	 rts instruction.  */
-      fprintf (file, ";OS_task epilogue\n");
-      fprintf (file, "\trts\n");
-      goto out;
-    }
-
-  /* Monitor epilogues are the same as interrupt function epilogues.
-     Just make a note that we're in a monitor epilogue.  */
-  if (h8300_monitor_function_p (current_function_decl))
-    fprintf (file, ";monitor epilogue\n");
-
-  /* If the last insn was a BARRIER, we don't have to write any code.  */
-  if (GET_CODE (insn) == NOTE)
-    insn = prev_nonnote_insn (insn);
-  if (insn && GET_CODE (insn) == BARRIER)
-    goto out;
+    /* OS_Task epilogues are nearly naked -- they just have an
+       rts instruction.  */
+    return;
 
   /* Pop the saved registers in descending order.  */
   saved_regs = compute_saved_regs ();
@@ -687,22 +628,22 @@ h8300_output_function_epilogue (file, size)
 	  switch (n_regs)
 	    {
 	    case 1:
-	      pop (file, regno);
+	      pop (regno);
 	      break;
 	    case 2:
-	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",
-		       h8_reg_names[regno - 1],
-		       h8_reg_names[regno]);
+	      emit_insn (gen_ldm_h8300s_2 (gen_rtx_REG (SImode, regno - 1),
+					   gen_rtx_REG (SImode, regno)));
 	      break;
 	    case 3:
-	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",
-		       h8_reg_names[regno - 2],
-		       h8_reg_names[regno]);
+	      emit_insn (gen_ldm_h8300s_3 (gen_rtx_REG (SImode, regno - 2),
+					   gen_rtx_REG (SImode, regno - 1),
+					   gen_rtx_REG (SImode, regno)));
 	      break;
 	    case 4:
-	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",
-		       h8_reg_names[regno - 3],
-		       h8_reg_names[regno]);
+	      emit_insn (gen_ldm_h8300s_4 (gen_rtx_REG (SImode, regno - 3),
+					   gen_rtx_REG (SImode, regno - 2),
+					   gen_rtx_REG (SImode, regno - 1),
+					   gen_rtx_REG (SImode, regno)));
 	      break;
 	    default:
 	      abort ();
@@ -711,21 +652,23 @@ h8300_output_function_epilogue (file, size)
     }
 
   /* Deallocate locals.  */
-  dosize (file, 1, fsize);
+  dosize (1, fsize);
 
   /* Pop frame pointer if we had one.  */
   if (frame_pointer_needed)
-    pop (file, FRAME_POINTER_REGNUM);
+    pop (FRAME_POINTER_REGNUM);
+}
 
-  if (h8300_current_function_interrupt_function_p ())
-    fprintf (file, "\trte\n");
-  else
-    fprintf (file, "\trts\n");
+/* Output assembly language code for the function epilogue.  */
 
- out:
+static void
+h8300_output_function_epilogue (file, size)
+     FILE *file ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
   pragma_saveall = 0;
 }
-
+  
 /* Return nonzero if the current function is an interrupt
    function.  */
 
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 6d0be34d4bd60cd8d0df978681dcc83bfb109298..6a9245ee8ae4ccf0e57354b20a67f0e8fea2bb16 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -51,7 +51,8 @@
 ;; ----------------------------------------------------------------------
 
 (define_constants
-  [(UNSPEC_INCDEC	0)])
+  [(UNSPEC_INCDEC	0)
+   (UNSPEC_MONITOR	1)])
 
 (define_constants
   [(SC_REG	 3)
@@ -1783,7 +1784,32 @@
 ;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_insn "*stm_h8300s_2"
+(define_expand "push_h8300"
+  [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
+        (match_operand:HI 0 "register_operand" "=r"))]
+	
+  "TARGET_H8300"
+  "")
+
+(define_expand "push_h8300hs"
+  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+        (match_operand:SI 0 "register_operand" "=r"))]
+  "TARGET_H8300H && TARGET_H8300S"
+  "")
+
+(define_expand "pop_h8300"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(mem:HI (post_inc:HI (reg:HI SP_REG))))]
+  "TARGET_H8300"
+  "")
+
+(define_expand "pop_h8300hs"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(mem:SI (post_inc:SI (reg:SI SP_REG))))]
+  "TARGET_H8300H && TARGET_H8300S"
+  "")
+
+(define_insn "stm_h8300s_2"
   [(parallel
      [(set (reg:SI SP_REG)
 	   (plus:SI (reg:SI SP_REG) (const_int -8)))
@@ -1799,7 +1825,7 @@
   [(set_attr "cc" "none")
    (set_attr "length" "4")])
 
-(define_insn "*stm_h8300s_3"
+(define_insn "stm_h8300s_3"
   [(parallel
      [(set (reg:SI SP_REG)
 	   (plus:SI (reg:SI SP_REG) (const_int -12)))
@@ -1820,7 +1846,7 @@
   [(set_attr "cc" "none")
    (set_attr "length" "4")])
 
-(define_insn "*stm_h8300s_4"
+(define_insn "stm_h8300s_4"
   [(parallel
      [(set (reg:SI SP_REG)
 	   (plus:SI (reg:SI SP_REG) (const_int -16)))
@@ -1840,6 +1866,107 @@
   "stm.l\\t%S0-%S3,@-er7"
   [(set_attr "cc" "none")
    (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_2"
+  [(parallel
+     [(set (reg:SI SP_REG)
+	   (plus:SI (reg:SI SP_REG) (const_int 8)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+	   (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (reg:SI SP_REG))
+	   (match_operand:SI 1 "register_operand" ""))])]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+       || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+       || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+  "ldm.l\\t@er7+,%S0-%S1"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_3"
+  [(parallel
+     [(set (reg:SI SP_REG)
+	   (plus:SI (reg:SI SP_REG) (const_int 12)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8)))
+	   (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+	   (match_operand:SI 1 "register_operand" ""))
+      (set (mem:SI (reg:SI SP_REG))
+	   (match_operand:SI 2 "register_operand" ""))])]
+  "TARGET_H8300S
+   && ((REGNO (operands[0]) == 0
+	&& REGNO (operands[1]) == 1
+	&& REGNO (operands[2]) == 2)
+       || (REGNO (operands[0]) == 4
+	   && REGNO (operands[1]) == 5
+	   && REGNO (operands[2]) == 6))"
+  "ldm.l\\t@er7+,%S0-%S2"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_4"
+  [(parallel
+     [(set (reg:SI SP_REG)
+	   (plus:SI (reg:SI SP_REG) (const_int 16)))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 12)))
+	   (match_operand:SI 0 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8)))
+	   (match_operand:SI 1 "register_operand" ""))
+      (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+	   (match_operand:SI 2 "register_operand" ""))
+      (set (mem:SI (reg:SI SP_REG))
+	   (match_operand:SI 3 "register_operand" ""))])]
+  "TARGET_H8300S
+   && REGNO (operands[0]) == 0
+   && REGNO (operands[1]) == 1
+   && REGNO (operands[2]) == 2
+   && REGNO (operands[3]) == 3"
+  "ldm.l\\t@er7+,%S0-%S3"
+  [(set_attr "cc" "none")
+   (set_attr "length" "4")])
+
+(define_expand "return"
+  [(return)]
+  "h8300_can_use_return_insn_p ()"
+  "")
+
+(define_insn "*return_1"
+  [(return)]
+  "reload_completed"
+  "*
+{
+  if (h8300_current_function_interrupt_function_p ())
+    return \"rte\";
+  else
+    return \"rts\";
+}"
+  [(set_attr "cc" "none")
+   (set_attr "length" "2")])
+
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "h8300_expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  "h8300_expand_epilogue ();")
+
+(define_insn "monitor_prologue"
+  [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)]
+  ""
+  "*
+{
+  if (TARGET_H8300)
+    return \"subs\\t#2,r7\;mov.w\\tr0,@-r7\;stc\\tccr,r0l\;mov.b\tr0l,@(2,r7)\;mov.w\\t@r7+,r0\;orc\t#128,ccr\";
+  else if (TARGET_H8300H)
+    return \"mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr\";
+  else if (TARGET_H8300S)
+    return \"stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr\";
+}"
+  [(set_attr "length" "20")
+   (set_attr "cc" "clobber")])
 
 ;; ----------------------------------------------------------------------
 ;; EXTEND INSTRUCTIONS