* amd64-tdep.c (amd64_convert_register_p): Delete.
[deliverable/binutils-gdb.git] / gdb / m68k-tdep.c
index aab2c33ec53b9274ef30ec94f6ba8186246832a1..b75a952e83fda447a3a3384731778a94709e2165 100644 (file)
@@ -1,13 +1,13 @@
 /* Target-dependent code for the Motorola 68000 series.
 
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000,
-   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
+   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "dwarf2-frame.h"
 #include "frame.h"
 #include "frame-base.h"
 #include "frame-unwind.h"
-#include "floatformat.h"
+#include "gdbtypes.h"
 #include "symtab.h"
 #include "gdbcore.h"
 #include "value.h"
@@ -36,6 +34,7 @@
 #include "arch-utils.h"
 #include "osabi.h"
 #include "dis-asm.h"
+#include "target-descriptions.h"
 
 #include "m68k-tdep.h"
 \f
 #define P_MOVEL_SP     0x2f00
 #define P_MOVEML_SP    0x48e7
 
-
-#define REGISTER_BYTES_FP (16*4 + 8 + 8*12 + 3*4)
-#define REGISTER_BYTES_NOFP (16*4 + 8)
-
 /* Offset from SP to first arg on stack at first instruction of a function */
 #define SP_ARG0 (1 * 4)
 
 #define BPT_VECTOR 0xf
 #endif
 
-static const unsigned char *
+static const gdb_byte *
 m68k_local_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
-  static unsigned char break_insn[] = {0x4e, (0x40 | BPT_VECTOR)};
+  static gdb_byte break_insn[] = {0x4e, (0x40 | BPT_VECTOR)};
   *lenptr = sizeof (break_insn);
   return break_insn;
 }
+\f
 
+/* Type for %ps.  */
+struct type *m68k_ps_type;
 
-static int
-m68k_register_bytes_ok (long numbytes)
+/* Construct types for ISA-specific registers.  */
+static void
+m68k_init_types (void)
 {
-  return ((numbytes == REGISTER_BYTES_FP)
-         || (numbytes == REGISTER_BYTES_NOFP));
+  struct type *type;
+
+  type = init_flags_type ("builtin_type_m68k_ps", 4);
+  append_flags_type_flag (type, 0, "C");
+  append_flags_type_flag (type, 1, "V");
+  append_flags_type_flag (type, 2, "Z");
+  append_flags_type_flag (type, 3, "N");
+  append_flags_type_flag (type, 4, "X");
+  append_flags_type_flag (type, 8, "I0");
+  append_flags_type_flag (type, 9, "I1");
+  append_flags_type_flag (type, 10, "I2");
+  append_flags_type_flag (type, 12, "M");
+  append_flags_type_flag (type, 13, "S");
+  append_flags_type_flag (type, 14, "T0");
+  append_flags_type_flag (type, 15, "T1");
+  m68k_ps_type = type;
 }
 
 /* Return the GDB type object for the "standard" data type of data in
@@ -92,43 +105,124 @@ m68k_register_bytes_ok (long numbytes)
 static struct type *
 m68k_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  if (regnum >= FP0_REGNUM && regnum <= FP0_REGNUM + 7)
-    return builtin_type_m68881_ext;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  if (regnum == M68K_FPI_REGNUM || regnum == PC_REGNUM)
-    return builtin_type_void_func_ptr;
+  if (tdep->fpregs_present)
+    {
+      if (regnum >= gdbarch_fp0_regnum (gdbarch)
+         && regnum <= gdbarch_fp0_regnum (gdbarch) + 7)
+       {
+         if (tdep->flavour == m68k_coldfire_flavour)
+           return builtin_type (gdbarch)->builtin_double;
+         else
+           return builtin_type_m68881_ext;
+       }
+
+      if (regnum == M68K_FPI_REGNUM)
+       return builtin_type_void_func_ptr;
 
-  if (regnum == M68K_FPC_REGNUM || regnum == M68K_FPS_REGNUM
-      || regnum == PS_REGNUM)
-    return builtin_type_int32;
+      if (regnum == M68K_FPC_REGNUM || regnum == M68K_FPS_REGNUM)
+       return builtin_type_int32;
+    }
+  else
+    {
+      if (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM)
+       return builtin_type_int0;
+    }
+
+  if (regnum == gdbarch_pc_regnum (gdbarch))
+    return builtin_type_void_func_ptr;
 
   if (regnum >= M68K_A0_REGNUM && regnum <= M68K_A0_REGNUM + 7)
     return builtin_type_void_data_ptr;
 
+  if (regnum == M68K_PS_REGNUM)
+    return m68k_ps_type;
+
   return builtin_type_int32;
 }
 
-/* Function: m68k_register_name
-   Returns the name of the standard m68k register regnum. */
-
-static const char *
-m68k_register_name (int regnum)
-{
-  static char *register_names[] = {
+static const char *m68k_register_names[] = {
     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
     "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp",
     "ps", "pc",
     "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
-    "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags"
+    "fpcontrol", "fpstatus", "fpiaddr"
   };
 
-  if (regnum < 0 ||
-      regnum >= sizeof (register_names) / sizeof (register_names[0]))
+/* Function: m68k_register_name
+   Returns the name of the standard m68k register regnum. */
+
+static const char *
+m68k_register_name (int regnum)
+{
+  if (regnum < 0 || regnum >= ARRAY_SIZE (m68k_register_names))
     internal_error (__FILE__, __LINE__,
-                   "m68k_register_name: illegal register number %d", regnum);
+                   _("m68k_register_name: illegal register number %d"), regnum);
   else
-    return register_names[regnum];
+    return m68k_register_names[regnum];
+}
+\f
+/* Return nonzero if a value of type TYPE stored in register REGNUM
+   needs any special handling.  */
+
+static int
+m68k_convert_register_p (int regnum, struct type *type)
+{
+  if (!gdbarch_tdep (current_gdbarch)->fpregs_present)
+    return 0;
+  return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FP0_REGNUM + 7
+         && type != builtin_type_m68881_ext);
+}
+
+/* Read a value of type TYPE from register REGNUM in frame FRAME, and
+   return its contents in TO.  */
+
+static void
+m68k_register_to_value (struct frame_info *frame, int regnum,
+                       struct type *type, gdb_byte *to)
+{
+  gdb_byte from[M68K_MAX_REGISTER_SIZE];
+  struct type *fpreg_type = register_type (get_frame_arch (frame),
+                                          M68K_FP0_REGNUM);
+
+  /* We only support floating-point values.  */
+  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      warning (_("Cannot convert floating-point register value "
+              "to non-floating-point type."));
+      return;
+    }
+
+  /* Convert to TYPE.  */
+  get_frame_register (frame, regnum, from);
+  convert_typed_floating (from, fpreg_type, to, type);
+}
+
+/* Write the contents FROM of a value of type TYPE into register
+   REGNUM in frame FRAME.  */
+
+static void
+m68k_value_to_register (struct frame_info *frame, int regnum,
+                       struct type *type, const gdb_byte *from)
+{
+  gdb_byte to[M68K_MAX_REGISTER_SIZE];
+  struct type *fpreg_type = register_type (get_frame_arch (frame),
+                                          M68K_FP0_REGNUM);
+
+  /* We only support floating-point values.  */
+  if (TYPE_CODE (type) != TYPE_CODE_FLT)
+    {
+      warning (_("Cannot convert non-floating-point type "
+              "to floating-point register value."));
+      return;
+    }
+
+  /* Convert from TYPE.  */
+  convert_typed_floating (from, type, to, fpreg_type);
+  put_frame_register (frame, regnum, to);
 }
+
 \f
 /* There is a fair number of calling conventions that are in somewhat
    wide use.  The 68000/08/10 don't support an FPU, not even as a
@@ -164,10 +258,10 @@ m68k_register_name (int regnum)
 
 static void
 m68k_extract_return_value (struct type *type, struct regcache *regcache,
-                          void *valbuf)
+                          gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  char buf[M68K_MAX_REGISTER_SIZE];
+  gdb_byte buf[M68K_MAX_REGISTER_SIZE];
 
   if (len <= 4)
     {
@@ -178,25 +272,27 @@ m68k_extract_return_value (struct type *type, struct regcache *regcache,
     {
       regcache_raw_read (regcache, M68K_D0_REGNUM, buf);
       memcpy (valbuf, buf + (8 - len), len - 4);
-      regcache_raw_read (regcache, M68K_D1_REGNUM,
-                        (char *) valbuf + (len - 4));
+      regcache_raw_read (regcache, M68K_D1_REGNUM, valbuf + (len - 4));
     }
   else
     internal_error (__FILE__, __LINE__,
-                   "Cannot extract return value of %d bytes long.", len);
+                   _("Cannot extract return value of %d bytes long."), len);
 }
 
 static void
 m68k_svr4_extract_return_value (struct type *type, struct regcache *regcache,
-                               void *valbuf)
+                               gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
-  char buf[M68K_MAX_REGISTER_SIZE];
+  gdb_byte buf[M68K_MAX_REGISTER_SIZE];
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+  if (tdep->float_return && TYPE_CODE (type) == TYPE_CODE_FLT)
     {
+      struct type *fpreg_type = register_type (gdbarch, M68K_FP0_REGNUM);
       regcache_raw_read (regcache, M68K_FP0_REGNUM, buf);
-      convert_typed_floating (buf, builtin_type_m68881_ext, valbuf, type);
+      convert_typed_floating (buf, fpreg_type, valbuf, type);
     }
   else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
     regcache_raw_read (regcache, M68K_A0_REGNUM, valbuf);
@@ -208,7 +304,7 @@ m68k_svr4_extract_return_value (struct type *type, struct regcache *regcache,
 
 static void
 m68k_store_return_value (struct type *type, struct regcache *regcache,
-                        const void *valbuf)
+                        const gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
 
@@ -218,24 +314,26 @@ m68k_store_return_value (struct type *type, struct regcache *regcache,
     {
       regcache_raw_write_part (regcache, M68K_D0_REGNUM, 8 - len,
                               len - 4, valbuf);
-      regcache_raw_write (regcache, M68K_D1_REGNUM,
-                         (char *) valbuf + (len - 4));
+      regcache_raw_write (regcache, M68K_D1_REGNUM, valbuf + (len - 4));
     }
   else
     internal_error (__FILE__, __LINE__,
-                   "Cannot store return value of %d bytes long.", len);
+                   _("Cannot store return value of %d bytes long."), len);
 }
 
 static void
 m68k_svr4_store_return_value (struct type *type, struct regcache *regcache,
-                             const void *valbuf)
+                             const gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+  if (tdep->float_return && TYPE_CODE (type) == TYPE_CODE_FLT)
     {
-      char buf[M68K_MAX_REGISTER_SIZE];
-      convert_typed_floating (valbuf, type, buf, builtin_type_m68881_ext);
+      struct type *fpreg_type = register_type (gdbarch, M68K_FP0_REGNUM);
+      gdb_byte buf[M68K_MAX_REGISTER_SIZE];
+      convert_typed_floating (valbuf, type, buf, fpreg_type);
       regcache_raw_write (regcache, M68K_FP0_REGNUM, buf);
     }
   else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
@@ -274,18 +372,30 @@ m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
 
 static enum return_value_convention
 m68k_return_value (struct gdbarch *gdbarch, struct type *type,
-                  struct regcache *regcache, void *readbuf,
-                  const void *writebuf)
+                  struct regcache *regcache, gdb_byte *readbuf,
+                  const gdb_byte *writebuf)
 {
   enum type_code code = TYPE_CODE (type);
 
-  if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
-      && !m68k_reg_struct_return_p (gdbarch, type))
-    return RETURN_VALUE_STRUCT_CONVENTION;
+  /* GCC returns a `long double' in memory too.  */
+  if (((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+       && !m68k_reg_struct_return_p (gdbarch, type))
+      || (code == TYPE_CODE_FLT && TYPE_LENGTH (type) == 12))
+    {
+      /* The default on m68k is to return structures in static memory.
+         Consequently a function must return the address where we can
+         find the return value.  */
+
+      if (readbuf)
+       {
+         ULONGEST addr;
+
+         regcache_raw_read_unsigned (regcache, M68K_D0_REGNUM, &addr);
+         read_memory (addr, readbuf, TYPE_LENGTH (type));
+       }
 
-  /* GCC returns a `long double' in memory.  */
-  if (code == TYPE_CODE_FLT && TYPE_LENGTH (type) == 12)
-    return RETURN_VALUE_STRUCT_CONVENTION;
+      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+    }
 
   if (readbuf)
     m68k_extract_return_value (type, regcache, readbuf);
@@ -297,14 +407,34 @@ m68k_return_value (struct gdbarch *gdbarch, struct type *type,
 
 static enum return_value_convention
 m68k_svr4_return_value (struct gdbarch *gdbarch, struct type *type,
-                       struct regcache *regcache, void *readbuf,
-                       const void *writebuf)
+                       struct regcache *regcache, gdb_byte *readbuf,
+                       const gdb_byte *writebuf)
 {
   enum type_code code = TYPE_CODE (type);
 
   if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
       && !m68k_reg_struct_return_p (gdbarch, type))
-    return RETURN_VALUE_STRUCT_CONVENTION;
+    {
+      /* The System V ABI says that:
+
+        "A function returning a structure or union also sets %a0 to
+        the value it finds in %a0.  Thus when the caller receives
+        control again, the address of the returned object resides in
+        register %a0."
+
+        So the ABI guarantees that we can always find the return
+        value just after the function has returned.  */
+
+      if (readbuf)
+       {
+         ULONGEST addr;
+
+         regcache_raw_read_unsigned (regcache, M68K_A0_REGNUM, &addr);
+         read_memory (addr, readbuf, TYPE_LENGTH (type));
+       }
+
+      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+    }
 
   /* This special case is for structures consisting of a single
      `float' or `double' member.  These structures are returned in
@@ -327,77 +457,31 @@ m68k_svr4_return_value (struct gdbarch *gdbarch, struct type *type,
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 \f
-int
-delta68_in_sigtramp (CORE_ADDR pc, char *name)
-{
-  if (name != NULL)
-    return strcmp (name, "_sigcode") == 0;
-  else
-    return 0;
-}
-
-CORE_ADDR
-delta68_frame_args_address (struct frame_info *frame_info)
-{
-  /* we assume here that the only frameless functions are the system calls
-     or other functions who do not put anything on the stack. */
-  if (get_frame_type (frame_info) == SIGTRAMP_FRAME)
-    return get_frame_base (frame_info) + 12;
-  else if (legacy_frameless_look_for_prologue (frame_info))
-    {
-      /* Check for an interrupted system call */
-      if (get_next_frame (frame_info) && (get_frame_type (get_next_frame (frame_info)) == SIGTRAMP_FRAME))
-       return get_frame_base (get_next_frame (frame_info)) + 16;
-      else
-       return get_frame_base (frame_info) + 4;
-    }
-  else
-    return get_frame_base (frame_info);
-}
 
-CORE_ADDR
-delta68_frame_saved_pc (struct frame_info *frame_info)
-{
-  return read_memory_unsigned_integer (delta68_frame_args_address (frame_info)
-                                      + 4, 4);
-}
+/* Always align the frame to a 4-byte boundary.  This is required on
+   coldfire and harmless on the rest.  */
 
-int
-delta68_frame_num_args (struct frame_info *fi)
+static CORE_ADDR
+m68k_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
 {
-  int val;
-  CORE_ADDR pc = DEPRECATED_FRAME_SAVED_PC (fi);
-  int insn = read_memory_unsigned_integer (pc, 2);
-  val = 0;
-  if (insn == 0047757 || insn == 0157374)      /* lea W(sp),sp or addaw #W,sp */
-    val = read_memory_integer (pc + 2, 2);
-  else if ((insn & 0170777) == 0050217 /* addql #N, sp */
-          || (insn & 0170777) == 0050117)      /* addqw */
-    {
-      val = (insn >> 9) & 7;
-      if (val == 0)
-       val = 8;
-    }
-  else if (insn == 0157774)    /* addal #WW, sp */
-    val = read_memory_integer (pc + 2, 4);
-  val >>= 2;
-  return val;
+  /* Align the stack to four bytes.  */
+  return sp & ~3;
 }
 
 static CORE_ADDR
-m68k_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+m68k_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                      struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
                      struct value **args, CORE_ADDR sp, int struct_return,
                      CORE_ADDR struct_addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  char buf[4];
+  gdb_byte buf[4];
   int i;
 
   /* Push arguments in reverse order.  */
   for (i = nargs - 1; i >= 0; i--)
     {
-      struct type *value_type = VALUE_ENCLOSING_TYPE (args[i]);
+      struct type *value_type = value_enclosing_type (args[i]);
       int len = TYPE_LENGTH (value_type);
       int container_len = (len + 3) & ~3;
       int offset;
@@ -412,7 +496,7 @@ m68k_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       else
        offset = container_len - len;
       sp -= container_len;
-      write_memory (sp + offset, VALUE_CONTENTS_ALL (args[i]), len);
+      write_memory (sp + offset, value_contents_all (args[i]), len);
     }
 
   /* Store struct value address.  */
@@ -438,6 +522,29 @@ m68k_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
      frame's CFA.  */
   return sp + 8;
 }
+
+/* Convert a dwarf or dwarf2 regnumber to a GDB regnum.  */
+
+static int
+m68k_dwarf_reg_to_regnum (int num)
+{
+  if (num < 8)
+    /* d0..7 */
+    return (num - 0) + M68K_D0_REGNUM;
+  else if (num < 16)
+    /* a0..7 */
+    return (num - 8) + M68K_A0_REGNUM;
+  else if (num < 24 && gdbarch_tdep (current_gdbarch)->fpregs_present)
+    /* fp0..7 */
+    return (num - 16) + M68K_FP0_REGNUM;
+  else if (num == 25)
+    /* pc */
+    return M68K_PC_REGNUM;
+  else
+    return gdbarch_num_regs (current_gdbarch)
+          + gdbarch_num_pseudo_regs (current_gdbarch);
+}
+
 \f
 struct m68k_frame_cache
 {
@@ -596,7 +703,8 @@ m68k_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
       while (pc < current_pc)
        {
          op = read_memory_unsigned_integer (pc, 2);
-         if (op == P_FMOVEMX_SP)
+         if (op == P_FMOVEMX_SP
+             && gdbarch_tdep (current_gdbarch)->fpregs_present)
            {
              /* fmovem.x REGS,-(%sp) */
              op = read_memory_unsigned_integer (pc + 2, 2);
@@ -616,10 +724,10 @@ m68k_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
              else
                break;
            }
-         else if ((op & 0170677) == P_MOVEL_SP)
+         else if ((op & 0177760) == P_MOVEL_SP)
            {
              /* move.l %R,-(%sp) */
-             regno = ((op & 07000) >> 9) | ((op & 0100) >> 3);
+             regno = op & 017;
              cache->saved_regs[regno] = offset;
              offset -= 4;
              pc += 2;
@@ -720,9 +828,9 @@ m68k_skip_prologue (CORE_ADDR start_pc)
 static CORE_ADDR
 m68k_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  char buf[8];
+  gdb_byte buf[8];
 
-  frame_unwind_register (next_frame, PC_REGNUM, buf);
+  frame_unwind_register (next_frame, gdbarch_pc_regnum (gdbarch), buf);
   return extract_typed_address (buf, builtin_type_void_func_ptr);
 }
 \f
@@ -732,7 +840,7 @@ static struct m68k_frame_cache *
 m68k_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
   struct m68k_frame_cache *cache;
-  char buf[4];
+  gdb_byte buf[4];
   int i;
 
   if (*this_cache)
@@ -758,7 +866,7 @@ m68k_frame_cache (struct frame_info *next_frame, void **this_cache)
   /* For normal frames, %pc is stored at 4(%fp).  */
   cache->saved_regs[M68K_PC_REGNUM] = 4;
 
-  cache->pc = frame_func_unwind (next_frame);
+  cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
   if (cache->pc != 0)
     m68k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
 
@@ -807,7 +915,7 @@ static void
 m68k_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 m68k_frame_cache *cache = m68k_frame_cache (next_frame, this_cache);
 
@@ -837,13 +945,17 @@ m68k_frame_prev_register (struct frame_info *next_frame, void **this_cache,
        {
          /* Read the value in from memory.  */
          read_memory (*addrp, valuep,
-                      register_size (current_gdbarch, regnum));
+                      register_size (get_frame_arch (next_frame), regnum));
        }
       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 const struct frame_unwind m68k_frame_unwind =
@@ -878,7 +990,7 @@ static const struct frame_base m68k_frame_base =
 static struct frame_id
 m68k_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  char buf[4];
+  gdb_byte buf[4];
   CORE_ADDR fp;
 
   frame_unwind_register (next_frame, M68K_FP_REGNUM, buf);
@@ -888,166 +1000,43 @@ m68k_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return frame_id_build (fp + 8, frame_pc_unwind (next_frame));
 }
 \f
-#ifdef USE_PROC_FS             /* Target dependent support for /proc */
-
-#include <sys/procfs.h>
-
-/* Prototypes for supply_gregset etc. */
-#include "gregset.h"
-
-/*  The /proc interface divides the target machine's register set up into
-   two different sets, the general register set (gregset) and the floating
-   point register set (fpregset).  For each set, there is an ioctl to get
-   the current register set and another ioctl to set the current values.
-
-   The actual structure passed through the ioctl interface is, of course,
-   naturally machine dependent, and is different for each set of registers.
-   For the m68k for example, the general register set is typically defined
-   by:
-
-   typedef int gregset_t[18];
-
-   #define      R_D0    0
-   ...
-   #define      R_PS    17
-
-   and the floating point set by:
-
-   typedef      struct fpregset {
-   int  f_pcr;
-   int  f_psr;
-   int  f_fpiaddr;
-   int  f_fpregs[8][3];         (8 regs, 96 bits each)
-   } fpregset_t;
-
-   These routines provide the packing and unpacking of gregset_t and
-   fpregset_t formatted data.
-
- */
-
-/* Atari SVR4 has R_SR but not R_PS */
-
-#if !defined (R_PS) && defined (R_SR)
-#define R_PS R_SR
-#endif
-
-/*  Given a pointer to a general register set in /proc format (gregset_t *),
-   unpack the register contents and supply them as gdb's idea of the current
-   register values. */
-
-void
-supply_gregset (gregset_t *gregsetp)
-{
-  int regi;
-  greg_t *regp = (greg_t *) gregsetp;
-
-  for (regi = 0; regi < R_PC; regi++)
-    {
-      supply_register (regi, (char *) (regp + regi));
-    }
-  supply_register (PS_REGNUM, (char *) (regp + R_PS));
-  supply_register (PC_REGNUM, (char *) (regp + R_PC));
-}
-
-void
-fill_gregset (gregset_t *gregsetp, int regno)
-{
-  int regi;
-  greg_t *regp = (greg_t *) gregsetp;
-
-  for (regi = 0; regi < R_PC; regi++)
-    {
-      if (regno == -1 || regno == regi)
-       regcache_collect (regi, regp + regi);
-    }
-  if (regno == -1 || regno == PS_REGNUM)
-    regcache_collect (PS_REGNUM, regp + R_PS);
-  if (regno == -1 || regno == PC_REGNUM)
-    regcache_collect (PC_REGNUM, regp + R_PC);
-}
-
-#if defined (FP0_REGNUM)
-
-/*  Given a pointer to a floating point register set in /proc format
-   (fpregset_t *), unpack the register contents and supply them as gdb's
-   idea of the current floating point register values. */
-
-void
-supply_fpregset (fpregset_t *fpregsetp)
-{
-  int regi;
-  char *from;
-
-  for (regi = FP0_REGNUM; regi < M68K_FPC_REGNUM; regi++)
-    {
-      from = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
-      supply_register (regi, from);
-    }
-  supply_register (M68K_FPC_REGNUM, (char *) &(fpregsetp->f_pcr));
-  supply_register (M68K_FPS_REGNUM, (char *) &(fpregsetp->f_psr));
-  supply_register (M68K_FPI_REGNUM, (char *) &(fpregsetp->f_fpiaddr));
-}
-
-/*  Given a pointer to a floating point register set in /proc format
-   (fpregset_t *), update the register specified by REGNO from gdb's idea
-   of the current floating point register set.  If REGNO is -1, update
-   them all. */
-
-void
-fill_fpregset (fpregset_t *fpregsetp, int regno)
-{
-  int regi;
-
-  for (regi = FP0_REGNUM; regi < M68K_FPC_REGNUM; regi++)
-    {
-      if (regno == -1 || regno == regi)
-       regcache_collect (regi, &fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
-    }
-  if (regno == -1 || regno == M68K_FPC_REGNUM)
-    regcache_collect (M68K_FPC_REGNUM, &fpregsetp->f_pcr);
-  if (regno == -1 || regno == M68K_FPS_REGNUM)
-    regcache_collect (M68K_FPS_REGNUM, &fpregsetp->f_psr);
-  if (regno == -1 || regno == M68K_FPI_REGNUM)
-    regcache_collect (M68K_FPI_REGNUM, &fpregsetp->f_fpiaddr);
-}
-
-#endif /* defined (FP0_REGNUM) */
-
-#endif /* USE_PROC_FS */
 
 /* Figure out where the longjmp will land.  Slurp the args out of the stack.
    We expect the first arg to be a pointer to the jmp_buf structure from which
    we extract the pc (JB_PC) that we will land at.  The pc is copied into PC.
    This routine returns true on success. */
 
-int
-m68k_get_longjmp_target (CORE_ADDR *pc)
+static int
+m68k_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
 {
-  char *buf;
+  gdb_byte *buf;
   CORE_ADDR sp, jb_addr;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
 
   if (tdep->jb_pc < 0)
     {
       internal_error (__FILE__, __LINE__,
-                     "m68k_get_longjmp_target: not implemented");
+                     _("m68k_get_longjmp_target: not implemented"));
       return 0;
     }
 
-  buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
-  sp = read_register (SP_REGNUM);
+  buf = alloca (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT);
+  sp = get_frame_register_unsigned (frame, gdbarch_sp_regnum (gdbarch));
 
   if (target_read_memory (sp + SP_ARG0,        /* Offset of first arg on stack */
-                         buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
+                         buf, gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT))
     return 0;
 
-  jb_addr = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+  jb_addr = extract_unsigned_integer (buf, gdbarch_ptr_bit (gdbarch)
+                                            / TARGET_CHAR_BIT);
 
   if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf,
-                         TARGET_PTR_BIT / TARGET_CHAR_BIT))
+                         gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT))
     return 0;
 
-  *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+  *pc = extract_unsigned_integer (buf, gdbarch_ptr_bit (gdbarch)
+                                        / TARGET_CHAR_BIT);
   return 1;
 }
 \f
@@ -1076,41 +1065,164 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch_tdep *tdep = NULL;
   struct gdbarch *gdbarch;
+  struct gdbarch_list *best_arch;
+  struct tdesc_arch_data *tdesc_data = NULL;
+  int i;
+  enum m68k_flavour flavour = m68k_no_flavour;
+  int has_fp = 1;
+  const struct floatformat **long_double_format = floatformats_m68881_ext;
+
+  /* Check any target description for validity.  */
+  if (tdesc_has_registers (info.target_desc))
+    {
+      const struct tdesc_feature *feature;
+      int valid_p;
+
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.m68k.core");
+      if (feature != NULL)
+       /* Do nothing.  */
+       ;
+
+      if (feature == NULL)
+       {
+         feature = tdesc_find_feature (info.target_desc,
+                                       "org.gnu.gdb.coldfire.core");
+         if (feature != NULL)
+           flavour = m68k_coldfire_flavour;
+       }
+
+      if (feature == NULL)
+       {
+         feature = tdesc_find_feature (info.target_desc,
+                                       "org.gnu.gdb.fido.core");
+         if (feature != NULL)
+           flavour = m68k_fido_flavour;
+       }
+
+      if (feature == NULL)
+       return NULL;
 
-  /* find a candidate among the list of pre-declared architectures. */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return (arches->gdbarch);
+      tdesc_data = tdesc_data_alloc ();
+
+      valid_p = 1;
+      for (i = 0; i <= M68K_PC_REGNUM; i++)
+       valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+                                           m68k_register_names[i]);
+
+      if (!valid_p)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.coldfire.fp");
+      if (feature != NULL)
+       {
+         valid_p = 1;
+         for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+                                               m68k_register_names[i]);
+         if (!valid_p)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
+       }
+      else
+       has_fp = 0;
+    }
+
+  /* The mechanism for returning floating values from function
+     and the type of long double depend on whether we're
+     on ColdFire or standard m68k. */
+
+  if (info.bfd_arch_info && info.bfd_arch_info->mach != 0)
+    {
+      const bfd_arch_info_type *coldfire_arch = 
+       bfd_lookup_arch (bfd_arch_m68k, bfd_mach_mcf_isa_a_nodiv);
+
+      if (coldfire_arch
+         && ((*info.bfd_arch_info->compatible) 
+             (info.bfd_arch_info, coldfire_arch)))
+       flavour = m68k_coldfire_flavour;
+    }
+  
+  /* If there is already a candidate, use it.  */
+  for (best_arch = gdbarch_list_lookup_by_info (arches, &info);
+       best_arch != NULL;
+       best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
+    {
+      if (flavour != gdbarch_tdep (best_arch->gdbarch)->flavour)
+       continue;
+
+      if (has_fp != gdbarch_tdep (best_arch->gdbarch)->fpregs_present)
+       continue;
+
+      break;
+    }
 
   tdep = xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->fpregs_present = has_fp;
+  tdep->flavour = flavour;
 
-  set_gdbarch_long_double_format (gdbarch, &floatformat_m68881_ext);
-  set_gdbarch_long_double_bit (gdbarch, 96);
+  if (flavour == m68k_coldfire_flavour || flavour == m68k_fido_flavour)
+    long_double_format = floatformats_ieee_double;
+  set_gdbarch_long_double_format (gdbarch, long_double_format);
+  set_gdbarch_long_double_bit (gdbarch, long_double_format[0]->totalsize);
 
   set_gdbarch_skip_prologue (gdbarch, m68k_skip_prologue);
   set_gdbarch_breakpoint_from_pc (gdbarch, m68k_local_breakpoint_from_pc);
 
   /* Stack grows down. */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  set_gdbarch_frame_align (gdbarch, m68k_frame_align);
 
   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
-  set_gdbarch_decr_pc_after_break (gdbarch, 2);
+  if (flavour == m68k_coldfire_flavour || flavour == m68k_fido_flavour)
+    set_gdbarch_decr_pc_after_break (gdbarch, 2);
 
   set_gdbarch_frame_args_skip (gdbarch, 8);
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch, m68k_dwarf_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, m68k_dwarf_reg_to_regnum);
 
   set_gdbarch_register_type (gdbarch, m68k_register_type);
   set_gdbarch_register_name (gdbarch, m68k_register_name);
-  set_gdbarch_num_regs (gdbarch, 29);
-  set_gdbarch_register_bytes_ok (gdbarch, m68k_register_bytes_ok);
+  set_gdbarch_num_regs (gdbarch, M68K_NUM_REGS);
   set_gdbarch_sp_regnum (gdbarch, M68K_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, M68K_PC_REGNUM);
   set_gdbarch_ps_regnum (gdbarch, M68K_PS_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, M68K_FP0_REGNUM);
+  set_gdbarch_convert_register_p (gdbarch, m68k_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch,  m68k_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, m68k_value_to_register);
+
+  if (has_fp)
+    set_gdbarch_fp0_regnum (gdbarch, M68K_FP0_REGNUM);
 
+  /* Try to figure out if the arch uses floating registers to return
+     floating point values from functions.  */
+  if (has_fp)
+    {
+      /* On ColdFire, floating point values are returned in D0.  */
+      if (flavour == m68k_coldfire_flavour)
+       tdep->float_return = 0;
+      else
+       tdep->float_return = 1;
+    }
+  else
+    {
+      /* No floating registers, so can't use them for returning values.  */
+      tdep->float_return = 0;
+    }
+
+  /* Function call & return */
   set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
   set_gdbarch_return_value (gdbarch, m68k_return_value);
 
+
   /* Disassembler.  */
   set_gdbarch_print_insn (gdbarch, print_insn_m68k);
 
@@ -1143,14 +1255,17 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   frame_unwind_append_sniffer (gdbarch, m68k_frame_sniffer);
 
+  if (tdesc_data)
+    tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
+
   return gdbarch;
 }
 
 
 static void
-m68k_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+m68k_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (tdep == NULL)
     return;
@@ -1162,4 +1277,7 @@ void
 _initialize_m68k_tdep (void)
 {
   gdbarch_register (bfd_arch_m68k, m68k_gdbarch_init, m68k_dump_tdep);
+
+  /* Initialize the m68k-specific register types.  */
+  m68k_init_types ();
 }
This page took 0.041657 seconds and 4 git commands to generate.