2005-11-23 Andrew Stubbs <andrew.stubbs@st.com>
[platform/upstream/binutils.git] / gdb / sh-tdep.c
index e983410..23bd3f0 100644 (file)
@@ -1,6 +1,7 @@
 /* Target-dependent code for Renesas Super-H, for GDB.
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004 Free Software Foundation, Inc.
+
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -411,6 +412,10 @@ sh_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
    r15-4-->r15, PR-->(r15) */
 #define IS_STS(x)              ((x) == 0x4f22)
 
+/* STS.L MACL,@-r15  0100111100010010
+   r15-4-->r15, MACL-->(r15) */
+#define IS_MACL_STS(x)         ((x) == 0x4f12)
+
 /* MOV.L Rm,@-r15  00101111mmmm0110
    r15-4-->r15, Rm-->(R15) */
 #define IS_PUSH(x)             (((x) & 0xff0f) == 0x2f06)
@@ -458,6 +463,8 @@ sh_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 #define IS_MOVW_PCREL_TO_REG(x)        (((x) & 0xf000) == 0x9000)
 /* MOV.L @(disp*4,PC),Rn      1101nnnndddddddd */
 #define IS_MOVL_PCREL_TO_REG(x)        (((x) & 0xf000) == 0xd000)
+/* MOVI20 #imm20,Rn           0000nnnniiii0000 */
+#define IS_MOVI20(x)           (((x) & 0xf00f) == 0x0000)
 /* SUB Rn,R15                 00111111nnnn1000 */
 #define IS_SUB_REG_FROM_SP(x)  (((x) & 0xff0f) == 0x3f08)
 
@@ -467,6 +474,7 @@ sh_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 #define IS_RESTORE_FP(x)       ((x) == 0x6ef6)
 #define IS_RTS(x)              ((x) == 0x000b)
 #define IS_LDS(x)              ((x) == 0x4f26)
+#define IS_MACL_LDS(x)         ((x) == 0x4f16)
 #define IS_MOV_FP_SP(x)        ((x) == 0x6fe3)
 #define IS_ADD_REG_TO_FP(x)    (((x) & 0xff0f) == 0x3e0c)
 #define IS_ADD_IMM_FP(x)       (((x) & 0xff00) == 0x7e00)
@@ -508,6 +516,11 @@ sh_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
          cache->saved_regs[PR_REGNUM] = cache->sp_offset;
          cache->sp_offset += 4;
        }
+      else if (IS_MACL_STS (inst))
+       {
+         cache->saved_regs[MACL_REGNUM] = cache->sp_offset;
+         cache->sp_offset += 4;
+       }
       else if (IS_MOV_R3 (inst))
        {
          r3_val = ((inst & 0xff) ^ 0x80) - 0x80;
@@ -553,6 +566,25 @@ sh_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
                }
            }
        }
+      else if (IS_MOVI20 (inst))
+        {
+         if (sav_reg < 0)
+           {
+             reg = GET_TARGET_REG (inst);
+             if (reg < 14)
+               {
+                 sav_reg = reg;
+                 sav_offset = GET_SOURCE_REG (inst) << 16;
+                 /* MOVI20 is a 32 bit instruction! */
+                 pc += 2;
+                 sav_offset |= read_memory_unsigned_integer (pc, 2);
+                 /* Now sav_offset contains an unsigned 20 bit value.
+                    It must still get sign extended.  */
+                 if (sav_offset & 0x00080000)
+                   sav_offset |= 0xfff00000;
+               }
+           }
+       }
       else if (IS_SUB_REG_FROM_SP (inst))
        {
          reg = GET_SOURCE_REG (inst);
@@ -845,12 +877,12 @@ sh_justify_value_in_reg (struct value *val, int len)
     {
       /* value gets right-justified in the register or stack word */
       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-       memcpy (valbuf + (4 - len), (char *) VALUE_CONTENTS (val), len);
+       memcpy (valbuf + (4 - len), (char *) value_contents (val), len);
       else
-       memcpy (valbuf, (char *) VALUE_CONTENTS (val), len);
+       memcpy (valbuf, (char *) value_contents (val), len);
       return valbuf;
     }
-  return (char *) VALUE_CONTENTS (val);
+  return (char *) value_contents (val);
 }
 
 /* Helper function to eval number of bytes to allocate on stack. */
@@ -859,7 +891,7 @@ sh_stack_allocsize (int nargs, struct value **args)
 {
   int stack_alloc = 0;
   while (nargs-- > 0)
-    stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[nargs])) + 3) & ~3);
+    stack_alloc += ((TYPE_LENGTH (value_type (args[nargs])) + 3) & ~3);
   return stack_alloc;
 }
 
@@ -1014,7 +1046,7 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
      in four registers available.  Loop thru args from first to last.  */
   for (argnum = 0; argnum < nargs; argnum++)
     {
-      type = VALUE_TYPE (args[argnum]);
+      type = value_type (args[argnum]);
       len = TYPE_LENGTH (type);
       val = sh_justify_value_in_reg (args[argnum], len);
 
@@ -1120,7 +1152,7 @@ sh_push_dummy_call_nofpu (struct gdbarch *gdbarch,
      in four registers available.  Loop thru args from first to last.  */
   for (argnum = 0; argnum < nargs; argnum++)
     {
-      type = VALUE_TYPE (args[argnum]);
+      type = value_type (args[argnum]);
       len = TYPE_LENGTH (type);
       val = sh_justify_value_in_reg (args[argnum], len);
 
@@ -1163,8 +1195,8 @@ sh_push_dummy_call_nofpu (struct gdbarch *gdbarch,
    containing the (raw) register state a function return value of type
    TYPE, and copy that, in virtual format, into VALBUF.  */
 static void
-sh_default_extract_return_value (struct type *type, struct regcache *regcache,
-                                void *valbuf)
+sh_extract_return_value_nofpu (struct type *type, struct regcache *regcache,
+                              void *valbuf)
 {
   int len = TYPE_LENGTH (type);
   int return_register = R0_REGNUM;
@@ -1184,12 +1216,12 @@ sh_default_extract_return_value (struct type *type, struct regcache *regcache,
        regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
     }
   else
-    error ("bad size for return value");
+    error (_("bad size for return value"));
 }
 
 static void
-sh3e_sh4_extract_return_value (struct type *type, struct regcache *regcache,
-                              void *valbuf)
+sh_extract_return_value_fpu (struct type *type, struct regcache *regcache,
+                            void *valbuf)
 {
   if (sh_treat_as_flt_p (type))
     {
@@ -1202,7 +1234,7 @@ sh3e_sh4_extract_return_value (struct type *type, struct regcache *regcache,
          regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
     }
   else
-    sh_default_extract_return_value (type, regcache, valbuf);
+    sh_extract_return_value_nofpu (type, regcache, valbuf);
 }
 
 /* Write into appropriate registers a function return value
@@ -1212,8 +1244,8 @@ sh3e_sh4_extract_return_value (struct type *type, struct regcache *regcache,
    depending on the type of the return value. In all the other cases
    the result is stored in r0, left-justified. */
 static void
-sh_default_store_return_value (struct type *type, struct regcache *regcache,
-                              const void *valbuf)
+sh_store_return_value_nofpu (struct type *type, struct regcache *regcache,
+                            const void *valbuf)
 {
   ULONGEST val;
   int len = TYPE_LENGTH (type);
@@ -1232,8 +1264,8 @@ sh_default_store_return_value (struct type *type, struct regcache *regcache,
 }
 
 static void
-sh3e_sh4_store_return_value (struct type *type, struct regcache *regcache,
-                            const void *valbuf)
+sh_store_return_value_fpu (struct type *type, struct regcache *regcache,
+                          const void *valbuf)
 {
   if (sh_treat_as_flt_p (type))
     {
@@ -1247,7 +1279,35 @@ sh3e_sh4_store_return_value (struct type *type, struct regcache *regcache,
          regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
     }
   else
-    sh_default_store_return_value (type, regcache, valbuf);
+    sh_store_return_value_nofpu (type, regcache, valbuf);
+}
+
+static enum return_value_convention
+sh_return_value_nofpu (struct gdbarch *gdbarch, struct type *type,
+                      struct regcache *regcache,
+                      gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  if (sh_use_struct_convention (0, type))
+    return RETURN_VALUE_STRUCT_CONVENTION;
+  if (writebuf)
+    sh_store_return_value_nofpu (type, regcache, writebuf);
+  else if (readbuf)
+    sh_extract_return_value_nofpu (type, regcache, readbuf);
+  return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+static enum return_value_convention
+sh_return_value_fpu (struct gdbarch *gdbarch, struct type *type,
+                    struct regcache *regcache,
+                    gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  if (sh_use_struct_convention (0, type))
+    return RETURN_VALUE_STRUCT_CONVENTION;
+  if (writebuf)
+    sh_store_return_value_fpu (type, regcache, writebuf);
+  else if (readbuf)
+    sh_extract_return_value_fpu (type, regcache, readbuf);
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
 /* Print the registers in a form similar to the E7000 */
@@ -1805,7 +1865,7 @@ sh_register_convert_to_raw (struct type *type, int regnum,
                                 &val, to);
     }
   else
-    error ("sh_register_convert_to_raw called with non DR register number");
+    error (_("sh_register_convert_to_raw called with non DR register number"));
 }
 
 /* For vectors of 4 floating point registers. */
@@ -1830,11 +1890,14 @@ dr_reg_base_num (int dr_regnum)
 
 static void
 sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-                        int reg_nr, void *buffer)
+                        int reg_nr, gdb_byte *buffer)
 {
   int base_regnum, portion;
   char temp_buffer[MAX_REGISTER_SIZE];
 
+  if (reg_nr == PSEUDO_BANK_REGNUM)
+    regcache_raw_read (regcache, BANK_REGNUM, buffer);
+  else
   if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
     {
       base_regnum = dr_reg_base_num (reg_nr);
@@ -1866,12 +1929,24 @@ sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
 static void
 sh_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
-                         int reg_nr, const void *buffer)
+                         int reg_nr, const gdb_byte *buffer)
 {
   int base_regnum, portion;
   char temp_buffer[MAX_REGISTER_SIZE];
 
-  if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
+  if (reg_nr == PSEUDO_BANK_REGNUM)
+    {
+      /* When the bank register is written to, the whole register bank
+         is switched and all values in the bank registers must be read
+        from the target/sim again. We're just invalidating the regcache
+        so that a re-read happens next time it's necessary.  */
+      int bregnum;
+
+      regcache_raw_write (regcache, BANK_REGNUM, buffer);
+      for (bregnum = R0_BANK0_REGNUM; bregnum < MACLB_REGNUM; ++bregnum)
+        set_register_cached (bregnum, 0);
+    }
+  else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
     {
       base_regnum = dr_reg_base_num (reg_nr);
 
@@ -1899,225 +1974,6 @@ sh_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
     }
 }
 
-/* Floating point vector of 4 float registers. */
-static void
-do_fv_register_info (struct gdbarch *gdbarch, struct ui_file *file,
-                    int fv_regnum)
-{
-  int first_fp_reg_num = fv_reg_base_num (fv_regnum);
-  fprintf_filtered (file, "fv%d\t0x%08x\t0x%08x\t0x%08x\t0x%08x\n",
-                   fv_regnum - FV0_REGNUM,
-                   (int) read_register (first_fp_reg_num),
-                   (int) read_register (first_fp_reg_num + 1),
-                   (int) read_register (first_fp_reg_num + 2),
-                   (int) read_register (first_fp_reg_num + 3));
-}
-
-/* Double precision registers. */
-static void
-do_dr_register_info (struct gdbarch *gdbarch, struct ui_file *file,
-                    int dr_regnum)
-{
-  int first_fp_reg_num = dr_reg_base_num (dr_regnum);
-
-  fprintf_filtered (file, "dr%d\t0x%08x%08x\n",
-                   dr_regnum - DR0_REGNUM,
-                   (int) read_register (first_fp_reg_num),
-                   (int) read_register (first_fp_reg_num + 1));
-}
-static void
-do_bank_register_info (struct gdbarch *gdbarch, struct ui_file *file)
-{
-  fprintf_filtered (file, "bank           %d\n",
-                   (int) read_register (BANK_REGNUM));
-}
-
-static void
-sh_print_pseudo_register (struct gdbarch *gdbarch, struct ui_file *file,
-                         int regnum)
-{
-  if (regnum < NUM_REGS || regnum >= NUM_REGS + NUM_PSEUDO_REGS)
-    internal_error (__FILE__, __LINE__,
-                   "Invalid pseudo register number %d\n", regnum);
-  else if (regnum == PSEUDO_BANK_REGNUM)
-    do_bank_register_info (gdbarch, file);
-  else if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
-    do_dr_register_info (gdbarch, file, regnum);
-  else if (regnum >= FV0_REGNUM && regnum <= FV_LAST_REGNUM)
-    do_fv_register_info (gdbarch, file, regnum);
-}
-
-static void
-sh_do_fp_register (struct gdbarch *gdbarch, struct ui_file *file, int regnum)
-{                              /* do values for FP (float) regs */
-  char *raw_buffer;
-  double flt;                  /* double extracted from raw hex data */
-  int inv;
-  int j;
-
-  /* Allocate space for the float. */
-  raw_buffer = (char *) alloca (register_size (gdbarch, FP0_REGNUM));
-
-  /* Get the data in raw format.  */
-  if (!frame_register_read (get_selected_frame (), regnum, raw_buffer))
-    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
-
-  /* Get the register as a number */
-  flt = unpack_double (builtin_type_float, raw_buffer, &inv);
-
-  /* Print the name and some spaces. */
-  fputs_filtered (REGISTER_NAME (regnum), file);
-  print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
-
-  /* Print the value. */
-  if (inv)
-    fprintf_filtered (file, "<invalid float>");
-  else
-    fprintf_filtered (file, "%-10.9g", flt);
-
-  /* Print the fp register as hex. */
-  fprintf_filtered (file, "\t(raw 0x");
-  for (j = 0; j < register_size (gdbarch, regnum); j++)
-    {
-      int idx = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                ? j
-                : register_size (gdbarch, regnum) - 1 - j);
-      fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[idx]);
-    }
-  fprintf_filtered (file, ")");
-  fprintf_filtered (file, "\n");
-}
-
-static void
-sh_do_register (struct gdbarch *gdbarch, struct ui_file *file, int regnum)
-{
-  char raw_buffer[MAX_REGISTER_SIZE];
-
-  fputs_filtered (REGISTER_NAME (regnum), file);
-  print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
-
-  /* Get the data in raw format.  */
-  if (!frame_register_read (get_selected_frame (), regnum, raw_buffer))
-    fprintf_filtered (file, "*value not available*\n");
-
-  val_print (gdbarch_register_type (gdbarch, regnum), raw_buffer, 0, 0,
-            file, 'x', 1, 0, Val_pretty_default);
-  fprintf_filtered (file, "\t");
-  val_print (gdbarch_register_type (gdbarch, regnum), raw_buffer, 0, 0,
-            file, 0, 1, 0, Val_pretty_default);
-  fprintf_filtered (file, "\n");
-}
-
-static void
-sh_print_register (struct gdbarch *gdbarch, struct ui_file *file, int regnum)
-{
-  if (regnum < 0 || regnum >= NUM_REGS + NUM_PSEUDO_REGS)
-    internal_error (__FILE__, __LINE__,
-                   "Invalid register number %d\n", regnum);
-
-  else if (regnum >= 0 && regnum < NUM_REGS)
-    {
-      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
-         TYPE_CODE_FLT)
-       sh_do_fp_register (gdbarch, file, regnum);      /* FP regs */
-      else
-       sh_do_register (gdbarch, file, regnum); /* All other regs */
-    }
-
-  else if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
-    {
-      sh_print_pseudo_register (gdbarch, file, regnum);
-    }
-}
-
-static void
-sh_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
-                        struct frame_info *frame, int regnum, int fpregs)
-{
-  if (regnum != -1)            /* do one specified register */
-    {
-      if (*(REGISTER_NAME (regnum)) == '\0')
-       error ("Not a valid register for the current processor type");
-
-      sh_print_register (gdbarch, file, regnum);
-    }
-  else
-    /* do all (or most) registers */
-    {
-      for (regnum = 0; regnum < NUM_REGS; ++regnum)
-       {
-         /* If the register name is empty, it is undefined for this
-            processor, so don't display anything.  */
-         if (REGISTER_NAME (regnum) == NULL
-             || *(REGISTER_NAME (regnum)) == '\0')
-           continue;
-
-         if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
-             TYPE_CODE_FLT)
-           {
-             /* true for "INFO ALL-REGISTERS" command */
-             if (fpregs)
-               sh_do_fp_register (gdbarch, file, regnum);      /* FP regs */
-           }
-         else
-           sh_do_register (gdbarch, file, regnum);     /* All other regs */
-       }
-
-      if (regnum == PSEUDO_BANK_REGNUM
-         && REGISTER_NAME (regnum)
-         && *REGISTER_NAME (regnum))
-       sh_print_pseudo_register (gdbarch, file, regnum++);
-
-      if (fpregs)
-       while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
-         {
-           sh_print_pseudo_register (gdbarch, file, regnum);
-           regnum++;
-         }
-    }
-}
-
-/* Fetch (and possibly build) an appropriate link_map_offsets structure
-   for native i386 linux targets using the struct offsets defined in
-   link.h (but without actual reference to that file).
-
-   This makes it possible to access i386-linux shared libraries from
-   a gdb that was not built on an i386-linux host (for cross debugging).
-   */
-
-struct link_map_offsets *
-sh_linux_svr4_fetch_link_map_offsets (void)
-{
-  static struct link_map_offsets lmo;
-  static struct link_map_offsets *lmp = 0;
-
-  if (lmp == 0)
-    {
-      lmp = &lmo;
-
-      lmo.r_debug_size = 8;    /* 20 not actual size but all we need */
-
-      lmo.r_map_offset = 4;
-      lmo.r_map_size = 4;
-
-      lmo.link_map_size = 20;  /* 552 not actual size but all we need */
-
-      lmo.l_addr_offset = 0;
-      lmo.l_addr_size = 4;
-
-      lmo.l_name_offset = 4;
-      lmo.l_name_size = 4;
-
-      lmo.l_next_offset = 12;
-      lmo.l_next_size = 4;
-
-      lmo.l_prev_offset = 16;
-      lmo.l_prev_size = 4;
-    }
-
-  return lmp;
-}
-
 static int
 sh_dsp_register_sim_regno (int nr)
 {
@@ -2248,7 +2104,7 @@ static void
 sh_frame_prev_register (struct frame_info *next_frame, void **this_cache,
                        int regnum, int *optimizedp,
                        enum lval_type *lvalp, CORE_ADDR *addrp,
-                       int *realnump, void *valuep)
+                       int *realnump, gdb_byte *valuep)
 {
   struct sh_frame_cache *cache = sh_frame_cache (next_frame, this_cache);
 
@@ -2289,8 +2145,12 @@ sh_frame_prev_register (struct frame_info *next_frame, void **this_cache,
       return;
     }
 
-  frame_register_unwind (next_frame, regnum,
-                        optimizedp, lvalp, addrp, realnump, valuep);
+  *optimizedp = 0;
+  *lvalp = lval_register;
+  *addrp = 0;
+  *realnump = regnum;
+  if (valuep)
+    frame_unwind_register (next_frame, (*realnump), valuep);
 }
 
 static void
@@ -2389,8 +2249,16 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
       else if (!IS_RESTORE_FP (read_memory_unsigned_integer (addr + 2, 2)))
        return 0;
 
-      /* Step over possible lds.l @r15+,pr. */
       inst = read_memory_unsigned_integer (addr - 2, 2);
+
+      /* Step over possible lds.l @r15+,macl. */
+      if (IS_MACL_LDS (inst))
+       {
+         addr -= 2;
+         inst = read_memory_unsigned_integer (addr - 2, 2);
+       }
+
+      /* Step over possible lds.l @r15+,pr. */
       if (IS_LDS (inst))
        {
          addr -= 2;
@@ -2413,13 +2281,20 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
          inst = read_memory_unsigned_integer (addr - 2, 2);
        }
 
+      /* On SH2a check if the previous instruction was perhaps a MOVI20.
+         That's allowed for the epilogue.  */
+      if ((gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a
+           || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a_nofpu)
+          && addr > func_addr + 6
+         && IS_MOVI20 (read_memory_unsigned_integer (addr - 4, 2)))
+       addr -= 4;
+
       if (pc >= addr)
        return 1;
     }
   return 0;
 }
-
-static gdbarch_init_ftype sh_gdbarch_init;
+\f
 
 static struct gdbarch *
 sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
@@ -2465,12 +2340,10 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       sh_show_regs = sh4_nofpu_show_regs;
       break;
 
-#if 0
     case bfd_mach_sh5:
       sh_show_regs = sh64_show_regs;
       /* SH5 is handled entirely in sh64-tdep.c */
       return sh64_gdbarch_init (info, arches);
-#endif
     }
 
   /* If there is already a candidate, use it.  */
@@ -2499,19 +2372,16 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_register_type (gdbarch, sh_default_register_type);
 
-  set_gdbarch_print_registers_info (gdbarch, sh_print_registers_info);
-
   set_gdbarch_breakpoint_from_pc (gdbarch, sh_breakpoint_from_pc);
-  set_gdbarch_deprecated_use_struct_convention (gdbarch, sh_use_struct_convention);
 
   set_gdbarch_print_insn (gdbarch, gdb_print_insn_sh);
   set_gdbarch_register_sim_regno (gdbarch, legacy_register_sim_regno);
 
   set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
 
-  set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
-  set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
-  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
+  set_gdbarch_return_value (gdbarch, sh_return_value_nofpu);
+  set_gdbarch_deprecated_extract_struct_value_address (gdbarch,
+                                           sh_extract_struct_value_address);
 
   set_gdbarch_skip_prologue (gdbarch, sh_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
@@ -2545,9 +2415,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_register_name (gdbarch, sh_sh2e_register_name);
       set_gdbarch_register_type (gdbarch, sh_sh3e_register_type);
       set_gdbarch_fp0_regnum (gdbarch, 25);
-      set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
-      set_gdbarch_extract_return_value (gdbarch,
-                                       sh3e_sh4_extract_return_value);
+      set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
       set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
       break;
 
@@ -2560,8 +2428,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_num_pseudo_regs (gdbarch, 9);
       set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
       set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
-      set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
-      set_gdbarch_extract_return_value (gdbarch, sh3e_sh4_extract_return_value);
+      set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
       set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
       break;
 
@@ -2590,9 +2457,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_register_name (gdbarch, sh_sh3e_register_name);
       set_gdbarch_register_type (gdbarch, sh_sh3e_register_type);
       set_gdbarch_fp0_regnum (gdbarch, 25);
-      set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
-      set_gdbarch_extract_return_value (gdbarch,
-                                       sh3e_sh4_extract_return_value);
+      set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
       set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
       break;
 
@@ -2609,9 +2474,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_num_pseudo_regs (gdbarch, 13);
       set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
       set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
-      set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
-      set_gdbarch_extract_return_value (gdbarch,
-                                       sh3e_sh4_extract_return_value);
+      set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
       set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
       break;
 
@@ -2648,5 +2511,5 @@ _initialize_sh_tdep (void)
 
   gdbarch_register (bfd_arch_sh, sh_gdbarch_init, NULL);
 
-  add_com ("regs", class_vars, sh_show_regs_command, "Print all registers");
+  add_com ("regs", class_vars, sh_show_regs_command, _("Print all registers"));
 }