* m68k-tdep.h (enum m68k_flavour): New.
(struct gdbarch_tdep): New fields float_return, flavour and fpregs_present. * m68k-tdep.c (m68k_register_type): Use fpregs_present and conditionalize floating registers type on flavour. (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. * Makefile.in (m68k-tdep.o): Update dependencies.
This commit is contained in:
parent
83cc5c53e5
commit
8ed86d01ca
@ -1,3 +1,33 @@
|
||||
2007-06-15 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* m68k-tdep.h (enum m68k_flavour): New.
|
||||
(struct gdbarch_tdep): New fields
|
||||
float_return, flavour and fpregs_present.
|
||||
* m68k-tdep.c (m68k_register_type): Use
|
||||
fpregs_present and conditionalize floating
|
||||
registers type on flavour.
|
||||
(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.
|
||||
* Makefile.in (m68k-tdep.o): Update dependencies.
|
||||
|
||||
2007-06-15 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* NEWS: Mention "info spu" commands and qXfer:spu:read and
|
||||
|
@ -2286,7 +2286,7 @@ m68k-tdep.o: m68k-tdep.c $(defs_h) $(dwarf2_frame_h) $(frame_h) \
|
||||
$(frame_base_h) $(frame_unwind_h) $(gdbtypes_h) $(symtab_h) \
|
||||
$(gdbcore_h) $(value_h) $(gdb_string_h) $(gdb_assert_h) \
|
||||
$(inferior_h) $(regcache_h) $(arch_utils_h) $(osabi_h) $(dis_asm_h) \
|
||||
$(m68k_tdep_h)
|
||||
$(m68k_tdep_h) $(target_descriptions_h)
|
||||
m88kbsd-nat.o: m88kbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
|
||||
$(target_h) $(m88k_tdep_h) $(inf_ptrace_h)
|
||||
m88k-tdep.o: m88k-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) $(frame_h) \
|
||||
|
213
gdb/m68k-tdep.c
213
gdb/m68k-tdep.c
@ -36,6 +36,7 @@
|
||||
#include "arch-utils.h"
|
||||
#include "osabi.h"
|
||||
#include "dis-asm.h"
|
||||
#include "target-descriptions.h"
|
||||
|
||||
#include "m68k-tdep.h"
|
||||
|
||||
@ -80,41 +81,58 @@ m68k_local_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
|
||||
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 (current_gdbarch);
|
||||
|
||||
if (regnum == M68K_FPI_REGNUM || regnum == PC_REGNUM)
|
||||
if (tdep->fpregs_present)
|
||||
{
|
||||
if (regnum >= FP0_REGNUM && regnum <= FP0_REGNUM + 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)
|
||||
return builtin_type_int32;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM)
|
||||
return builtin_type_int0;
|
||||
}
|
||||
|
||||
if (regnum == PC_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_A0_REGNUM && regnum <= M68K_A0_REGNUM + 7)
|
||||
return builtin_type_void_data_ptr;
|
||||
|
||||
return builtin_type_int32;
|
||||
}
|
||||
|
||||
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"
|
||||
};
|
||||
|
||||
/* 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[] = {
|
||||
"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"
|
||||
};
|
||||
|
||||
if (regnum < 0 || regnum >= ARRAY_SIZE (register_names))
|
||||
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 +141,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 +154,7 @@ 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 (current_gdbarch, M68K_FP0_REGNUM);
|
||||
|
||||
/* We only support floating-point values. */
|
||||
if (TYPE_CODE (type) != TYPE_CODE_FLT)
|
||||
@ -146,7 +167,7 @@ m68k_register_to_value (struct frame_info *frame, int regnum,
|
||||
/* 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 +178,7 @@ 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 (current_gdbarch, M68K_FP0_REGNUM);
|
||||
|
||||
/* We only support floating-point values. */
|
||||
if (TYPE_CODE (type) != TYPE_CODE_FLT)
|
||||
@ -168,7 +190,7 @@ m68k_value_to_register (struct frame_info *frame, int regnum,
|
||||
|
||||
/* 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 +256,14 @@ m68k_svr4_extract_return_value (struct type *type, struct regcache *regcache,
|
||||
{
|
||||
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 +297,14 @@ m68k_svr4_store_return_value (struct type *type, struct regcache *regcache,
|
||||
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 +505,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)
|
||||
@ -646,7 +674,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);
|
||||
@ -1007,17 +1036,113 @@ 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;
|
||||
|
||||
/* find a candidate among the list of pre-declared architectures. */
|
||||
arches = gdbarch_list_lookup_by_info (arches, &info);
|
||||
if (arches != NULL)
|
||||
return (arches->gdbarch);
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
@ -1027,6 +1152,8 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
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);
|
||||
@ -1043,9 +1170,30 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
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);
|
||||
|
||||
@ -1078,6 +1226,9 @@ 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, tdesc_data);
|
||||
|
||||
return gdbarch;
|
||||
}
|
||||
|
||||
|
@ -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,16 @@ 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;
|
||||
|
||||
/* 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. */
|
||||
|
@ -45,10 +45,12 @@
|
||||
int
|
||||
m68kbsd_fpreg_offset (int regnum)
|
||||
{
|
||||
int fp_len = TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum));
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user