This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


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

ColdFire/fido support


This patch adds initial support for ColdFire and fido versions of m68k.
The primary difference is different format of floating point, and different
return convention for floating point values on coldfire. This patch also
adds support for XML description, which allows remote stub to
advertise presense of floating point registers in a clean way.

No change in behaviour for classic m68k-tdep.c is expected. OK?

- Volodya

Attachment: 2.ChangeLog
Description: Text document

--- gdb/m68k-tdep.c	(/patches/gdb/coldfire_1)	(revision 4079)
+++ gdb/m68k-tdep.c	(/patches/gdb/coldfire_2)	(revision 4079)
@@ -36,6 +36,7 @@
 #include "arch-utils.h"
 #include "osabi.h"
 #include "dis-asm.h"
+#include "target-descriptions.h"
 
 #include "m68k-tdep.h"
 
@@ -80,15 +81,25 @@ m68k_local_breakpoint_from_pc (CORE_ADDR
 static struct type *
 m68k_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  if (regnum >= FP0_REGNUM && regnum <= FP0_REGNUM + 7)
-    return builtin_type_m68881_ext;
+  if (gdbarch_tdep (gdbarch)->fpregs_present)
+    {
+      if (regnum >= FP0_REGNUM && regnum <= FP0_REGNUM + 7)
+	return *gdbarch_tdep (gdbarch)->fpreg_type;
 
-  if (regnum == M68K_FPI_REGNUM || regnum == PC_REGNUM)
-    return builtin_type_void_func_ptr;
+      if (regnum == M68K_FPI_REGNUM)
+	return builtin_type_void_func_ptr;
+
+      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 == M68K_FPC_REGNUM || regnum == M68K_FPS_REGNUM
-      || regnum == PS_REGNUM)
-    return builtin_type_int32;
+  if (regnum == PC_REGNUM)
+    return builtin_type_void_func_ptr;
 
   if (regnum >= M68K_A0_REGNUM && regnum <= M68K_A0_REGNUM + 7)
     return builtin_type_void_data_ptr;
@@ -96,25 +107,25 @@ m68k_register_type (struct gdbarch *gdba
   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 >= ARRAY_SIZE (register_names))
+/* 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);
   else
-    return register_names[regnum];
+    return m68k_register_names[regnum];
 }
 
 /* Return nonzero if a value of type TYPE stored in register REGNUM
@@ -123,6 +134,8 @@ m68k_register_name (int regnum)
 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);
 }
 
@@ -134,6 +147,7 @@ m68k_register_to_value (struct frame_inf
 			struct type *type, gdb_byte *to)
 {
   gdb_byte from[M68K_MAX_REGISTER_SIZE];
+  struct type *fpreg_type = register_type (current_gdbarch, M68K_FP0_REGNUM);
 
   /* We only support floating-point values.  */
   if (TYPE_CODE (type) != TYPE_CODE_FLT)
@@ -146,7 +160,7 @@ m68k_register_to_value (struct frame_inf
   /* Convert to TYPE.  This should be a no-op if TYPE is equivalent to
      the extended floating-point format used by the FPU.  */
   get_frame_register (frame, regnum, from);
-  convert_typed_floating (from, builtin_type_m68881_ext, to, type);
+  convert_typed_floating (from, fpreg_type, to, type);
 }
 
 /* Write the contents FROM of a value of type TYPE into register
@@ -157,6 +171,7 @@ m68k_value_to_register (struct frame_inf
 			struct type *type, const gdb_byte *from)
 {
   gdb_byte to[M68K_MAX_REGISTER_SIZE];
+  struct type *fpreg_type = register_type (current_gdbarch, M68K_FP0_REGNUM);
 
   /* We only support floating-point values.  */
   if (TYPE_CODE (type) != TYPE_CODE_FLT)
@@ -168,7 +183,7 @@ m68k_value_to_register (struct frame_inf
 
   /* Convert from TYPE.  This should be a no-op if TYPE is equivalent
      to the extended floating-point format used by the FPU.  */
-  convert_typed_floating (from, type, to, builtin_type_m68881_ext);
+  convert_typed_floating (from, type, to, fpreg_type);
   put_frame_register (frame, regnum, to);
 }
 
@@ -234,11 +249,14 @@ m68k_svr4_extract_return_value (struct t
 {
   int len = TYPE_LENGTH (type);
   gdb_byte buf[M68K_MAX_REGISTER_SIZE];
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+  if (tdep->float_return && TYPE_CODE (type) == TYPE_CODE_FLT)
     {
+      struct type *fpreg_type = register_type 
+	(current_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);
@@ -272,11 +290,14 @@ m68k_svr4_store_return_value (struct typ
 			      const gdb_byte *valbuf)
 {
   int len = TYPE_LENGTH (type);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+  if (tdep->float_return && TYPE_CODE (type) == TYPE_CODE_FLT)
     {
+      struct type *fpreg_type = register_type 
+	(current_gdbarch, M68K_FP0_REGNUM);
       gdb_byte buf[M68K_MAX_REGISTER_SIZE];
-      convert_typed_floating (valbuf, type, buf, builtin_type_m68881_ext);
+      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)
@@ -477,7 +498,7 @@ m68k_dwarf_reg_to_regnum (int num)
   else if (num < 16)
     /* a0..7 */
     return (num - 8) + M68K_A0_REGNUM;
-  else if (num < 24)
+  else if (num < 24 && gdbarch_tdep (current_gdbarch)->fpregs_present)
     /* fp0..7 */
     return (num - 16) + M68K_FP0_REGNUM;
   else if (num == 25)
@@ -645,7 +666,8 @@ m68k_analyze_register_saves (CORE_ADDR p
       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);
@@ -1136,17 +1158,118 @@ m68k_gdbarch_init (struct gdbarch_info i
 {
   struct gdbarch_tdep *tdep = NULL;
   struct gdbarch *gdbarch;
+  struct gdbarch_list *best_arch;
+  struct tdesc_arch_data *tdesc_data = NULL;
+  int i;
+  int coldfire = 0;
+  int fido = 0;
+  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)
+	    coldfire = 1;
+	}
+
+      if (feature == NULL)
+	{
+	  feature = tdesc_find_feature (info.target_desc,
+					"org.gnu.gdb.fido.core");
+	  if (feature != NULL)
+	    fido = 1;
+	}
+
+      if (feature == NULL)
+	return NULL;
+
+      tdesc_data = tdesc_data_alloc ();
 
-  /* find a candidate among the list of pre-declared architectures. */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return (arches->gdbarch);
+      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)
+    {
+      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))
+	coldfire = 1;
+    }
+  
+  /* 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 (coldfire != gdbarch_tdep (best_arch->gdbarch)->coldfire)
+	continue;
+
+      if (fido != gdbarch_tdep (best_arch->gdbarch)->fido)
+	continue;
+
+      if (has_fp != gdbarch_tdep (best_arch->gdbarch)->fpregs_present)
+	continue;
+
+      break;
+    }
 
   tdep = xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
-
-  set_gdbarch_long_double_format (gdbarch, floatformats_m68881_ext);
-  set_gdbarch_long_double_bit (gdbarch, 96);
+  tdep->fpregs_present = has_fp;
+  tdep->coldfire = coldfire;
+  tdep->fido = fido;
+
+  if (coldfire || fido)
+    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);
@@ -1156,6 +1279,8 @@ m68k_gdbarch_init (struct gdbarch_info i
   set_gdbarch_frame_align (gdbarch, m68k_frame_align);
 
   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+  if (coldfire || fido)
+    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);
@@ -1172,9 +1297,35 @@ m68k_gdbarch_init (struct gdbarch_info i
   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);
+
+  if (coldfire)
+    tdep->fpreg_type = &builtin_type_double;
+  else
+    tdep->fpreg_type = &builtin_type_m68881_ext;
+
+  /* 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 (coldfire)
+	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);
 
@@ -1207,6 +1358,9 @@ m68k_gdbarch_init (struct gdbarch_info i
 
   frame_unwind_append_sniffer (gdbarch, m68k_frame_sniffer);
 
+  if (tdesc_data)
+    tdesc_use_registers (gdbarch, tdesc_data);
+
   return gdbarch;
 }
 
--- gdb/m68k-tdep.h	(/patches/gdb/coldfire_1)	(revision 4079)
+++ gdb/m68k-tdep.h	(/patches/gdb/coldfire_2)	(revision 4079)
@@ -76,6 +76,27 @@ struct gdbarch_tdep
 
   /* Convention for returning structures.  */
   enum struct_return struct_return;
+
+  /* Convention for returning floats.  zero in int regs, non-zero in float.  */
+  int float_return;
+
+  /* Type of an fpreg.  NULL if there are no fpregs.  This is a
+     pointer to the pointer to type struct, because when architecture
+     init function is running, the types for the old architecture are swapped
+     out, and the types for the new architecture are not yet swapped in,
+     so all types that don't have specific sizes (like builting_type_double)
+     are NULL.  */
+  struct type **fpreg_type;
+
+  /* Is this ColdFire architecture, as opposed to generic m68k?  */
+  int coldfire;
+ 
+  /* Is this fido architecture, as opposed to generic m68k?  */
+  int fido;
+
+  /* Flag set if the floating point registers are present, or assumed
+     to be present.  */
+  int fpregs_present;
 };
 
 /* Initialize a SVR4 architecture variant.  */
--- gdb/m68kbsd-tdep.c	(/patches/gdb/coldfire_1)	(revision 4079)
+++ gdb/m68kbsd-tdep.c	(/patches/gdb/coldfire_2)	(revision 4079)
@@ -45,10 +45,12 @@
 int
 m68kbsd_fpreg_offset (int regnum)
 {
+  int fp_len = TYPE_LENGTH (*gdbarch_tdep (current_gdbarch)->fpreg_type);
+  
   if (regnum >= M68K_FPC_REGNUM)
-    return 8 * 12 + (regnum - M68K_FPC_REGNUM) * 4;
+    return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4;
 
-  return (regnum - M68K_FP0_REGNUM) * 12;
+  return (regnum - M68K_FP0_REGNUM) * fp_len;
 }
 
 /* Supply register REGNUM from the buffer specified by FPREGS and LEN

Property changes on: 
___________________________________________________________________
Name: svk:merge
 +d48a11ec-ee1c-0410-b3f5-c20844f99675:/patches/gdb/coldfire_submission:4065


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