Re: ColdFire/fido support

Vladimir Prus
2007-05-28T11:43:03Z

[-- Attachment #1: Type: text/plain, Size: 580 bytes --]

On Sunday 06 May 2007 15:52, Vladimir Prus wrote:
> On Saturday 05 May 2007 15:02, Andreas Schwab wrote:
> > Vladimir Prus <vladimir@codesourcery.com> writes:
> >
> > > + /* Is this ColdFire architecture, as opposed to generic m68k? */
> > > + int coldfire;
> > > +
> > > + /* Is this fido architecture, as opposed to generic m68k? */
> > > + int fido;
> >
> > How about making this a single enum? They surely can never both be
> > non-zero at the same time.
>
> Good idea. Here's a revised patch.

Any comments? I attach the patch again for convenience.

- Volodya

[-- Attachment #2: 2.ChangeLog --]
[-- Type: text/plain, Size: 1086 bytes --]

* m68k-tdep.h (enum m68k_flavour): New.
(struct gdbarch_tdep): New fields
float_return, fpreg_type, flavour and
fpregs_present.
* m68k-tdep.c (m68k_register_type): Use
fpregs_present and fpreg_type.
(m68k_register_names): New.
(m68k_register_name): Use the above.
(m68k_convert_register_p): Consult fpregs_present.
(m68k_register_to_value, m68k_value_to_register):
Use register_type to obtain the type of floating
point registers.
(m68k_svr4_extract_return_value): Check tdep->float_return.
Use register_type to get the type of floating
point regiters.
(m68k_svr4_store_return_value): Likewise.
(m68k_dwarf_reg_to_regnum): Check tdep->fpregs_present.
(m68k_analyze_register_saves): Likewise.
(m68k_gdbarch_init): Extract infromation
from XML description, if present. Guess coldfire by
looking at the file, if present. Conditionalize
setting of long double format. Set decr_pc_after_break
to 2 on coldfire and fido. Enable XML-driven
register description.
* m68kbsd-tdep.c (m68kbsd_fpreg_offset): Use
size of tdep->fpreg_type, as opposed to hardcoded value.

[-- Attachment #3: 2.diff --]
[-- Type: text/x-diff, Size: 13793 bytes --]

--- gdb/m68k-tdep.c (/patches/gdb/coldfire_1) (revision 4123)
+++ gdb/m68k-tdep.c (/patches/gdb/coldfire_2) (revision 4123)
@@ -36,6 +36,7 @@
#include "arch-utils.h"
#include "osabi.h"
#include "dis-asm.h"
+#include "target-descriptions.h"

#include "m68k-tdep.h"
\f
@@ -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];
}
\f
/* 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,113 @@ 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;
+ 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)
+ {
+ 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, floatformats_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);
@@ -1156,6 +1274,8 @@ m68k_gdbarch_init (struct gdbarch_info i
set_gdbarch_frame_align (gdbarch, m68k_frame_align);

set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+ 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);
@@ -1172,9 +1292,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 (flavour == m68k_coldfire_flavour)
+ 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 (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);

@@ -1207,6 +1353,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 4123)
+++ gdb/m68k-tdep.h (/patches/gdb/coldfire_2) (revision 4123)
@@ -60,6 +60,14 @@ enum struct_return
reg_struct_return /* Return "short" structures in registers. */
};

+/* Particular flavour of m68k. */
+enum m68k_flavour
+ {
+ m68k_no_flavour,
+ m68k_coldfire_flavour,
+ m68k_fido_flavour
+ };
+
/* Target-dependent structure in gdbarch. */

struct gdbarch_tdep
@@ -76,6 +84,24 @@ 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;
+
+ /* The particular flavour of m68k. */
+ enum m68k_flavour flavour;
+
+ /* 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 4123)
+++ gdb/m68kbsd-tdep.c (/patches/gdb/coldfire_2) (revision 4123)
@@ -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