h8300-protos.h: Add prototypes for the new functions defined below.
authorKazu Hirata <kazu@cs.umass.edu>
Sat, 4 Jan 2003 17:46:24 +0000 (17:46 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Sat, 4 Jan 2003 17:46:24 +0000 (17:46 +0000)
* 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.

From-SVN: r60882

gcc/ChangeLog
gcc/config/h8300/h8300-protos.h
gcc/config/h8300/h8300.c
gcc/config/h8300/h8300.md

index 70c1556..f5ee6e6 100644 (file)
@@ -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,
index 1ea1ab2..f5a59d4 100644 (file)
@@ -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 *));
index 5e4063c..f8ec682 100644 (file)
@@ -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.  */
 
index 6d0be34..6a9245e 100644 (file)
@@ -51,7 +51,8 @@
 ;; ----------------------------------------------------------------------
 
 (define_constants
-  [(UNSPEC_INCDEC      0)])
+  [(UNSPEC_INCDEC      0)
+   (UNSPEC_MONITOR     1)])
 
 (define_constants
   [(SC_REG      3)
 ;; 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)))
   [(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)))
   [(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)))
   "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")])
 \f
 ;; ----------------------------------------------------------------------
 ;; EXTEND INSTRUCTIONS