* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Check the selected
soft float and vector ABIs. Support the generic vector ABI for AltiVec types. (do_ppc_sysv_return_value): Likewise. Correct argument types and casts. (ppc64_sysv_abi_push_dummy_call): Assert that floating point is supported. * ppc-tdep.h (enum powerpc_vector_abi): New. (struct gdbarch_tdep): Add soft_float and vector_abi. * rs6000-tdep.c (setpowerpccmdlist, showpowerpccmdlist) (powerpc_soft_float_global, powerpc_vector_strings) (powerpc_vector_abi_global, powerpc_vector_abi_string): New. (rs6000_gdbarch_init): Check for soft-float and vector ABI markings. (set_powerpc_command, show_powerpc_command, powerpc_set_soft_float) (powerpc_set_vector_abi): New. (_initialize_rs6000_tdep): Register "set powerpc" and "show powerpc" commands. * Makefile.in (elf_ppc_h): New. (rs6000-tdep.o): Update. * gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set powerpc soft-float". * gdb.arch/altivec-abi.exp: Run multiple times for GCC on GNU/Linux. Test "set powerpc vector-abi". Skip auto-detection tests for old toolchains.
This commit is contained in:
parent
7020f05c27
commit
55eddb0f7a
|
@ -1,3 +1,25 @@
|
|||
2007-10-30 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Check the selected
|
||||
soft float and vector ABIs. Support the generic vector ABI for
|
||||
AltiVec types.
|
||||
(do_ppc_sysv_return_value): Likewise. Correct argument types and
|
||||
casts.
|
||||
(ppc64_sysv_abi_push_dummy_call): Assert that floating point is
|
||||
supported.
|
||||
* ppc-tdep.h (enum powerpc_vector_abi): New.
|
||||
(struct gdbarch_tdep): Add soft_float and vector_abi.
|
||||
* rs6000-tdep.c (setpowerpccmdlist, showpowerpccmdlist)
|
||||
(powerpc_soft_float_global, powerpc_vector_strings)
|
||||
(powerpc_vector_abi_global, powerpc_vector_abi_string): New.
|
||||
(rs6000_gdbarch_init): Check for soft-float and vector ABI markings.
|
||||
(set_powerpc_command, show_powerpc_command, powerpc_set_soft_float)
|
||||
(powerpc_set_vector_abi): New.
|
||||
(_initialize_rs6000_tdep): Register "set powerpc" and "show powerpc"
|
||||
commands.
|
||||
* Makefile.in (elf_ppc_h): New.
|
||||
(rs6000-tdep.o): Update.
|
||||
|
||||
2007-10-29 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
|
||||
|
||||
* ppc-linux-tdep.c (ppc32_linux_reg_offsets): Corrected
|
||||
|
|
|
@ -604,6 +604,7 @@ elf_bfd_h = $(BFD_SRC)/elf-bfd.h
|
|||
elf_frv_h = $(INCLUDE_DIR)/elf/frv.h $(elf_reloc_macros_h)
|
||||
elf_m32c_h = $(INCLUDE_DIR)/elf/m32c.h $(elf_reloc_macros_h)
|
||||
elf_mep_h = $(INCLUDE_DIR)/elf/mep.h $(elf_reloc_macros_h)
|
||||
elf_ppc_h = $(INCLUDE_DIR)/elf/ppc.h $(elf_reloc_macros_h)
|
||||
libaout_h = $(BFD_SRC)/libaout.h
|
||||
libiberty_h = $(INCLUDE_DIR)/libiberty.h
|
||||
libbfd_h = $(BFD_SRC)/libbfd.h
|
||||
|
@ -2578,7 +2579,7 @@ rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \
|
|||
$(coff_xcoff_h) $(libxcoff_h) $(elf_bfd_h) $(solib_svr4_h) \
|
||||
$(ppc_tdep_h) $(gdb_assert_h) $(dis_asm_h) $(trad_frame_h) \
|
||||
$(frame_unwind_h) $(frame_base_h) $(rs6000_tdep_h) $(dwarf2_frame_h) \
|
||||
$(target_descriptions) $(user_regs_h) \
|
||||
$(target_descriptions) $(user_regs_h) $(elf_ppc_h) \
|
||||
$(powerpc_32_c) $(powerpc_403_c) $(powerpc_403gc_c) $(powerpc_505_c) \
|
||||
$(powerpc_601_c) $(powerpc_602_c) $(powerpc_603_c) $(powerpc_604_c) \
|
||||
$(powerpc_64_c) $(powerpc_7400_c) $(powerpc_750_c) $(powerpc_860_c) \
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2007-10-30 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set
|
||||
powerpc soft-float".
|
||||
|
||||
2007-10-24 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Files): Correct formatting. Mention Expat
|
||||
|
|
|
@ -14937,7 +14937,25 @@ Set suspend trace mode.
|
|||
@node PowerPC
|
||||
@subsection PowerPC
|
||||
|
||||
@value{GDBN} provides the following PowerPC-specific commands:
|
||||
|
||||
@table @code
|
||||
@kindex set powerpc
|
||||
@item set powerpc soft-float
|
||||
@itemx show powerpc soft-float
|
||||
Force @value{GDBN} to use (or not use) a software floating point calling
|
||||
convention. By default, @value{GDBN} selects the calling convention based
|
||||
on the selected architecture and the provided executable file.
|
||||
|
||||
@item set powerpc vector-abi
|
||||
@itemx show powerpc vector-abi
|
||||
Force @value{GDBN} to use the specified calling convention for vector
|
||||
arguments and return values. The valid options are @samp{auto};
|
||||
@samp{generic}, to avoid vector registers even if they are present;
|
||||
@samp{altivec}, to use AltiVec registers; and @samp{spe} to use SPE
|
||||
registers. By default, @value{GDBN} selects the calling convention
|
||||
based on the selected architecture and the provided executable file.
|
||||
|
||||
@kindex target dink32
|
||||
@item target dink32 @var{dev}
|
||||
DINK32 ROM monitor.
|
||||
|
@ -14955,7 +14973,7 @@ SDS monitor, running on a PowerPC board (such as Motorola's ADS).
|
|||
|
||||
@cindex SDS protocol
|
||||
The following commands specific to the SDS protocol are supported
|
||||
by@value{GDBN}:
|
||||
by @value{GDBN}:
|
||||
|
||||
@table @code
|
||||
@item set sdstimeout @var{nsec}
|
||||
|
|
|
@ -104,8 +104,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
int len = TYPE_LENGTH (type);
|
||||
const bfd_byte *val = value_contents (arg);
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT
|
||||
&& ppc_floating_point_unit_p (current_gdbarch) && len <= 8)
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8
|
||||
&& !tdep->soft_float)
|
||||
{
|
||||
/* Floating point value converted to "double" then
|
||||
passed in an FP register, when the registers run out,
|
||||
|
@ -141,10 +141,11 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
argoffset += 8;
|
||||
}
|
||||
}
|
||||
else if (len == 8 && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */
|
||||
|| (!ppc_floating_point_unit_p (current_gdbarch) && TYPE_CODE (type) == TYPE_CODE_FLT))) /* double */
|
||||
else if (len == 8
|
||||
&& (TYPE_CODE (type) == TYPE_CODE_INT /* long long */
|
||||
|| TYPE_CODE (type) == TYPE_CODE_FLT)) /* double */
|
||||
{
|
||||
/* "long long" or "double" passed in an odd/even
|
||||
/* "long long" or soft-float "double" passed in an odd/even
|
||||
register pair with the low addressed word in the odd
|
||||
register and the high addressed word in the even
|
||||
register, or when the registers run out an 8 byte
|
||||
|
@ -184,7 +185,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
}
|
||||
else if (len == 16
|
||||
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
|
||||
&& TYPE_VECTOR (type)
|
||||
&& tdep->vector_abi == POWERPC_VEC_ALTIVEC)
|
||||
{
|
||||
/* Vector parameter passed in an Altivec register, or
|
||||
when that runs out, 16 byte aligned stack location. */
|
||||
|
@ -205,7 +207,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
}
|
||||
else if (len == 8
|
||||
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
|
||||
&& TYPE_VECTOR (type)
|
||||
&& tdep->vector_abi == POWERPC_VEC_SPE)
|
||||
{
|
||||
/* Vector parameter passed in an e500 register, or when
|
||||
that runs out, 8 byte aligned stack location. Note
|
||||
|
@ -239,9 +242,15 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
|| TYPE_CODE (type) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (type) == TYPE_CODE_UNION)
|
||||
{
|
||||
/* Structs and large values are put on an 8 byte
|
||||
aligned stack ... */
|
||||
structoffset = align_up (structoffset, 8);
|
||||
/* Structs and large values are put in an
|
||||
aligned stack slot ... */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_VECTOR (type)
|
||||
&& len >= 16)
|
||||
structoffset = align_up (structoffset, 16);
|
||||
else
|
||||
structoffset = align_up (structoffset, 8);
|
||||
|
||||
if (write_pass)
|
||||
write_memory (sp + structoffset, val, len);
|
||||
/* ... and then a "word" pointing to that address is
|
||||
|
@ -337,14 +346,14 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
|
||||
static enum return_value_convention
|
||||
do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
|
||||
struct regcache *regcache, void *readbuf,
|
||||
const void *writebuf, int broken_gcc)
|
||||
struct regcache *regcache, gdb_byte *readbuf,
|
||||
const gdb_byte *writebuf, int broken_gcc)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
gdb_assert (tdep->wordsize == 4);
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT
|
||||
&& TYPE_LENGTH (type) <= 8
|
||||
&& ppc_floating_point_unit_p (gdbarch))
|
||||
&& !tdep->soft_float)
|
||||
{
|
||||
if (readbuf)
|
||||
{
|
||||
|
@ -374,17 +383,17 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
|
|||
{
|
||||
/* A long long, or a double stored in the 32 bit r3/r4. */
|
||||
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
|
||||
(bfd_byte *) readbuf + 0);
|
||||
readbuf + 0);
|
||||
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
|
||||
(bfd_byte *) readbuf + 4);
|
||||
readbuf + 4);
|
||||
}
|
||||
if (writebuf)
|
||||
{
|
||||
/* A long long, or a double stored in the 32 bit r3/r4. */
|
||||
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
|
||||
(const bfd_byte *) writebuf + 0);
|
||||
writebuf + 0);
|
||||
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
|
||||
(const bfd_byte *) writebuf + 4);
|
||||
writebuf + 4);
|
||||
}
|
||||
return RETURN_VALUE_REGISTER_CONVENTION;
|
||||
}
|
||||
|
@ -417,7 +426,8 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
|
|||
}
|
||||
if (TYPE_LENGTH (type) == 16
|
||||
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
|
||||
&& TYPE_VECTOR (type)
|
||||
&& tdep->vector_abi == POWERPC_VEC_ALTIVEC)
|
||||
{
|
||||
if (readbuf)
|
||||
{
|
||||
|
@ -431,9 +441,42 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
|
|||
}
|
||||
return RETURN_VALUE_REGISTER_CONVENTION;
|
||||
}
|
||||
if (TYPE_LENGTH (type) == 16
|
||||
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_VECTOR (type)
|
||||
&& tdep->vector_abi == POWERPC_VEC_GENERIC)
|
||||
{
|
||||
/* GCC -maltivec -mabi=no-altivec returns vectors in r3/r4/r5/r6.
|
||||
GCC without AltiVec returns them in memory, but it warns about
|
||||
ABI risks in that case; we don't try to support it. */
|
||||
if (readbuf)
|
||||
{
|
||||
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
|
||||
readbuf + 0);
|
||||
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
|
||||
readbuf + 4);
|
||||
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
|
||||
readbuf + 8);
|
||||
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
|
||||
readbuf + 12);
|
||||
}
|
||||
if (writebuf)
|
||||
{
|
||||
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
|
||||
writebuf + 0);
|
||||
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
|
||||
writebuf + 4);
|
||||
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
|
||||
writebuf + 8);
|
||||
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
|
||||
writebuf + 12);
|
||||
}
|
||||
return RETURN_VALUE_REGISTER_CONVENTION;
|
||||
}
|
||||
if (TYPE_LENGTH (type) == 8
|
||||
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
|
||||
&& TYPE_VECTOR (type)
|
||||
&& tdep->vector_abi == POWERPC_VEC_SPE)
|
||||
{
|
||||
/* The e500 ABI places return values for the 64-bit DSP types
|
||||
(__ev64_opaque__) in r3. However, in GDB-speak, ev3
|
||||
|
@ -604,6 +647,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
the possible values of tdep->wordsize. */
|
||||
gdb_assert (tdep->wordsize == 8);
|
||||
|
||||
/* This function exists to support a calling convention that
|
||||
requires floating-point registers. It shouldn't be used on
|
||||
processors that lack them. */
|
||||
gdb_assert (ppc_floating_point_unit_p (gdbarch));
|
||||
|
||||
/* By this stage in the proceedings, SP has been decremented by "red
|
||||
zone size" + "struct return size". Fetch the stack-pointer from
|
||||
before this and use that as the BACK_CHAIN. */
|
||||
|
@ -685,8 +733,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
memory. */
|
||||
if (write_pass)
|
||||
{
|
||||
if (ppc_floating_point_unit_p (current_gdbarch)
|
||||
&& freg <= 13)
|
||||
if (freg <= 13)
|
||||
{
|
||||
gdb_byte regval[MAX_REGISTER_SIZE];
|
||||
struct type *regtype
|
||||
|
@ -869,7 +916,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||
}
|
||||
|
||||
|
||||
/* The 64 bit ABI retun value convention.
|
||||
/* The 64 bit ABI return value convention.
|
||||
|
||||
Return non-zero if the return-value is stored in a register, return
|
||||
0 if the return-value is instead stored on the stack (a.k.a.,
|
||||
|
|
|
@ -157,9 +157,24 @@ extern void ppc_collect_vrregset (const struct regset *regset,
|
|||
|
||||
/* Private data that this module attaches to struct gdbarch. */
|
||||
|
||||
/* Vector ABI used by the inferior. */
|
||||
enum powerpc_vector_abi
|
||||
{
|
||||
POWERPC_VEC_AUTO,
|
||||
POWERPC_VEC_GENERIC,
|
||||
POWERPC_VEC_ALTIVEC,
|
||||
POWERPC_VEC_SPE,
|
||||
POWERPC_VEC_LAST
|
||||
};
|
||||
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
int wordsize; /* size in bytes of fixed-point word */
|
||||
int wordsize; /* Size in bytes of fixed-point word. */
|
||||
int soft_float; /* Avoid FP registers for arguments? */
|
||||
|
||||
/* How to pass vector arguments. Never set to AUTO or LAST. */
|
||||
enum powerpc_vector_abi vector_abi;
|
||||
|
||||
int ppc_gp0_regnum; /* GPR register 0 */
|
||||
int ppc_toc_regnum; /* TOC register */
|
||||
int ppc_ps_regnum; /* Processor (or machine) status (%msr) */
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "libxcoff.h"
|
||||
|
||||
#include "elf-bfd.h"
|
||||
#include "elf/ppc.h"
|
||||
|
||||
#include "solib-svr4.h"
|
||||
#include "ppc-tdep.h"
|
||||
|
@ -77,6 +78,27 @@
|
|||
#include "features/rs6000/powerpc-e500.c"
|
||||
#include "features/rs6000/rs6000.c"
|
||||
|
||||
/* The list of available "set powerpc ..." and "show powerpc ..."
|
||||
commands. */
|
||||
static struct cmd_list_element *setpowerpccmdlist = NULL;
|
||||
static struct cmd_list_element *showpowerpccmdlist = NULL;
|
||||
|
||||
static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO;
|
||||
|
||||
/* The vector ABI to use. Keep this in sync with powerpc_vector_abi. */
|
||||
static const char *powerpc_vector_strings[] =
|
||||
{
|
||||
"auto",
|
||||
"generic",
|
||||
"altivec",
|
||||
"spe",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* A variable that can be configured by the user. */
|
||||
static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
|
||||
static const char *powerpc_vector_abi_string = "auto";
|
||||
|
||||
/* If the kernel has to deliver a signal, it pushes a sigcontext
|
||||
structure on the stack and then calls the signal handler, passing
|
||||
the address of the sigcontext in an argument register. Usually
|
||||
|
@ -3145,6 +3167,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
bfd abfd;
|
||||
int sysv_abi;
|
||||
asection *sect;
|
||||
enum auto_boolean soft_float_flag = powerpc_soft_float_global;
|
||||
int soft_float;
|
||||
enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
|
||||
int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0;
|
||||
int tdesc_wordsize = -1;
|
||||
const struct target_desc *tdesc = info.target_desc;
|
||||
|
@ -3417,6 +3442,76 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ELF
|
||||
if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
|
||||
{
|
||||
switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
|
||||
Tag_GNU_Power_ABI_FP))
|
||||
{
|
||||
case 1:
|
||||
soft_float_flag = AUTO_BOOLEAN_FALSE;
|
||||
break;
|
||||
case 2:
|
||||
soft_float_flag = AUTO_BOOLEAN_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vector_abi == POWERPC_VEC_AUTO && from_elf_exec)
|
||||
{
|
||||
switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
|
||||
Tag_GNU_Power_ABI_Vector))
|
||||
{
|
||||
case 1:
|
||||
vector_abi = POWERPC_VEC_GENERIC;
|
||||
break;
|
||||
case 2:
|
||||
vector_abi = POWERPC_VEC_ALTIVEC;
|
||||
break;
|
||||
case 3:
|
||||
vector_abi = POWERPC_VEC_SPE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (soft_float_flag == AUTO_BOOLEAN_TRUE)
|
||||
soft_float = 1;
|
||||
else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
|
||||
soft_float = 0;
|
||||
else
|
||||
soft_float = !have_fpu;
|
||||
|
||||
/* If we have a hard float binary or setting but no floating point
|
||||
registers, downgrade to soft float anyway. We're still somewhat
|
||||
useful in this scenario. */
|
||||
if (!soft_float && !have_fpu)
|
||||
soft_float = 1;
|
||||
|
||||
/* Similarly for vector registers. */
|
||||
if (vector_abi == POWERPC_VEC_ALTIVEC && !have_altivec)
|
||||
vector_abi = POWERPC_VEC_GENERIC;
|
||||
|
||||
if (vector_abi == POWERPC_VEC_SPE && !have_spe)
|
||||
vector_abi = POWERPC_VEC_GENERIC;
|
||||
|
||||
if (vector_abi == POWERPC_VEC_AUTO)
|
||||
{
|
||||
if (have_altivec)
|
||||
vector_abi = POWERPC_VEC_ALTIVEC;
|
||||
else if (have_spe)
|
||||
vector_abi = POWERPC_VEC_SPE;
|
||||
else
|
||||
vector_abi = POWERPC_VEC_GENERIC;
|
||||
}
|
||||
|
||||
/* Do not limit the vector ABI based on available hardware, since we
|
||||
do not yet know what hardware we'll decide we have. Yuck! FIXME! */
|
||||
|
||||
/* Find a candidate among extant architectures. */
|
||||
for (arches = gdbarch_list_lookup_by_info (arches, &info);
|
||||
arches != NULL;
|
||||
|
@ -3426,6 +3521,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform
|
||||
separate word size check. */
|
||||
tdep = gdbarch_tdep (arches->gdbarch);
|
||||
if (tdep && tdep->soft_float != soft_float)
|
||||
continue;
|
||||
if (tdep && tdep->vector_abi != vector_abi)
|
||||
continue;
|
||||
if (tdep && tdep->wordsize == wordsize)
|
||||
{
|
||||
if (tdesc_data != NULL)
|
||||
|
@ -3444,6 +3543,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
|
||||
tdep = XCALLOC (1, struct gdbarch_tdep);
|
||||
tdep->wordsize = wordsize;
|
||||
tdep->soft_float = soft_float;
|
||||
tdep->vector_abi = vector_abi;
|
||||
|
||||
gdbarch = gdbarch_alloc (&info, tdep);
|
||||
|
||||
|
@ -3643,6 +3744,61 @@ rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
|
|||
/* FIXME: Dump gdbarch_tdep. */
|
||||
}
|
||||
|
||||
/* PowerPC-specific commands. */
|
||||
|
||||
static void
|
||||
set_powerpc_command (char *args, int from_tty)
|
||||
{
|
||||
printf_unfiltered (_("\
|
||||
\"set powerpc\" must be followed by an appropriate subcommand.\n"));
|
||||
help_list (setpowerpccmdlist, "set powerpc ", all_commands, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
show_powerpc_command (char *args, int from_tty)
|
||||
{
|
||||
cmd_show_list (showpowerpccmdlist, from_tty, "");
|
||||
}
|
||||
|
||||
static void
|
||||
powerpc_set_soft_float (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
|
||||
/* Update the architecture. */
|
||||
gdbarch_info_init (&info);
|
||||
if (!gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__, "could not update architecture");
|
||||
}
|
||||
|
||||
static void
|
||||
powerpc_set_vector_abi (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
enum powerpc_vector_abi vector_abi;
|
||||
|
||||
for (vector_abi = POWERPC_VEC_AUTO;
|
||||
vector_abi != POWERPC_VEC_LAST;
|
||||
vector_abi++)
|
||||
if (strcmp (powerpc_vector_abi_string,
|
||||
powerpc_vector_strings[vector_abi]) == 0)
|
||||
{
|
||||
powerpc_vector_abi_global = vector_abi;
|
||||
break;
|
||||
}
|
||||
|
||||
if (vector_abi == POWERPC_VEC_LAST)
|
||||
internal_error (__FILE__, __LINE__, _("Invalid vector ABI accepted: %s."),
|
||||
powerpc_vector_abi_string);
|
||||
|
||||
/* Update the architecture. */
|
||||
gdbarch_info_init (&info);
|
||||
if (!gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__, "could not update architecture");
|
||||
}
|
||||
|
||||
/* Initialization code. */
|
||||
|
||||
extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
|
||||
|
@ -3668,4 +3824,30 @@ _initialize_rs6000_tdep (void)
|
|||
initialize_tdesc_powerpc_860 ();
|
||||
initialize_tdesc_powerpc_e500 ();
|
||||
initialize_tdesc_rs6000 ();
|
||||
|
||||
/* Add root prefix command for all "set powerpc"/"show powerpc"
|
||||
commands. */
|
||||
add_prefix_cmd ("powerpc", no_class, set_powerpc_command,
|
||||
_("Various PowerPC-specific commands."),
|
||||
&setpowerpccmdlist, "set powerpc ", 0, &setlist);
|
||||
|
||||
add_prefix_cmd ("powerpc", no_class, show_powerpc_command,
|
||||
_("Various PowerPC-specific commands."),
|
||||
&showpowerpccmdlist, "show powerpc ", 0, &showlist);
|
||||
|
||||
/* Add a command to allow the user to force the ABI. */
|
||||
add_setshow_auto_boolean_cmd ("soft-float", class_support,
|
||||
&powerpc_soft_float_global,
|
||||
_("Set whether to use a soft-float ABI."),
|
||||
_("Show whether to use a soft-float ABI."),
|
||||
NULL,
|
||||
powerpc_set_soft_float, NULL,
|
||||
&setpowerpccmdlist, &showpowerpccmdlist);
|
||||
|
||||
add_setshow_enum_cmd ("vector-abi", class_support, powerpc_vector_strings,
|
||||
&powerpc_vector_abi_string,
|
||||
_("Set the vector ABI."),
|
||||
_("Show the vector ABI."),
|
||||
NULL, powerpc_set_vector_abi, NULL,
|
||||
&setpowerpccmdlist, &showpowerpccmdlist);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2007-10-30 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.arch/altivec-abi.exp: Run multiple times for GCC on GNU/Linux.
|
||||
Test "set powerpc vector-abi". Skip auto-detection tests for old
|
||||
toolchains.
|
||||
|
||||
2007-10-30 Pedro Alves <pedro_alves@portugalmail.pt>
|
||||
|
||||
* lib/gdb.exp, gdb.base/sepdebug.exp: Replace usage of eq and ne
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Please email any bugs, comments, and/or additions to this file to:
|
||||
# bug-gdb@prep.ai.mit.edu
|
||||
#
|
||||
|
||||
# Tests for Powerpc AltiVec ABI
|
||||
|
||||
|
@ -28,9 +25,6 @@ if $tracelevel then {
|
|||
# This file uses altivec-abi.c for input.
|
||||
#
|
||||
|
||||
set prms_id 0
|
||||
set bug_id 0
|
||||
|
||||
if {![istarget "powerpc*"] || [skip_altivec_tests]} then {
|
||||
verbose "Skipping altivec abi tests."
|
||||
verbose -log "Skipping altivec abi tests."
|
||||
|
@ -41,88 +35,124 @@ set testfile "altivec-abi"
|
|||
set binfile ${objdir}/${subdir}/${testfile}
|
||||
set srcfile ${testfile}.c
|
||||
|
||||
set compile_flags {debug nowarnings}
|
||||
if [get_compiler_info $binfile] {
|
||||
warning "get_compiler failed"
|
||||
return -1
|
||||
}
|
||||
|
||||
proc altivec_abi_tests { extra_flags force_abi } {
|
||||
global testfile binfile srcfile srcdir subdir
|
||||
global gdb_prompt
|
||||
|
||||
set compile_flags "debug nowarnings $extra_flags"
|
||||
|
||||
if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
|
||||
untested altivec-abi.exp
|
||||
return -1
|
||||
}
|
||||
|
||||
if { "$force_abi" == "auto" } {
|
||||
# If the toolchain does not record attributes, skip auto-ABI tests.
|
||||
set readelf_program [transform readelf]
|
||||
set result [catch "exec $readelf_program -A $binfile" output]
|
||||
|
||||
if {$result == 0 && ![regexp Tag_GNU_Power_ABI_Vector $output]} {
|
||||
untested "ABI not marked"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
gdb_load ${binfile}
|
||||
|
||||
# Run to `main' where we begin our tests.
|
||||
if ![runto_main] then {
|
||||
untested altivec-abi.exp
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_test "set powerpc vector-abi $force_abi"
|
||||
|
||||
gdb_test "b marker" "Breakpoint 2 at.*file.*altivec-abi.c, line \[0-9\]+." "break marker"
|
||||
gdb_test "continue" "Breakpoint 2.*marker.*altivec-abi.c.*" "continue to marker"
|
||||
gdb_test "finish" "Run till exit from .0.*marker.*at.*altivec-abi.c.*main \\(\\) at.*altivec-abi.c.*result = vec_func \\(vshort,.*goes in v2.*" "back to main (1)"
|
||||
|
||||
# now all the arguments of vec_fun are initialized
|
||||
|
||||
set pattern "vec_func .vshort_f=.111, 222, 333, 444, 555, 666, 777, 888., vushort_f=.100, 200, 300, 400, 500, 600, 700, 800., vint_f=.-10, -20, -30, -40., vuint_f=.1111, 2222, 3333, 4444., vchar_f=.abcdefghilmnopqr., vuchar_f=.ABCDEFGHILMNOPQR., vfloat_f=.1.25, 3.75, 5.5, 1.25., x_f=.1, 2, 3, 4, 5, 6, 7, 8., y_f=.12, 22, 32, 42., a_f=.vector of chars.., b_f=.5.5, 4.5, 3.75, 2.25., c_f=.1.25, 3.5, 5.5, 7.75., intv_on_stack_f=.12, 34, 56, 78.."
|
||||
|
||||
set pattern1 $pattern
|
||||
append pattern1 " at.*altivec-abi.c.*vint_res = vec_add.*vint_f, intv_on_stack_f.;"
|
||||
|
||||
# Now let's call the function. This function has > 12 args,
|
||||
# the last one will go on the stack.
|
||||
set msg "call inferior function with vectors (1)"
|
||||
gdb_test "p vec_func(vshort,vushort,vint,vuint,vchar,vuchar,vfloat,x,y,a,b,c,intv_on_stack)" \
|
||||
".\[0-9\]+ = .2, 2, 2, 2." "call inferior function with vectors (1)"
|
||||
|
||||
# Let's call the function again with dummy arguments. This is to clean
|
||||
# up the contents of the vector registers before the next call.
|
||||
gdb_test "p vec_func(vshort_d,vushort_d,vint_d,vuint_d,vchar_d,vuchar_d,vfloat_d,x_d,y_d,a_d,b_d,c_d,intv_on_stack_d)" \
|
||||
".\[0-9\]+ = .0, 0, 0, 0." "call inferior function with vectors (2)"
|
||||
|
||||
# Let's step into the function, to see if the args are printed correctly.
|
||||
gdb_test "step" \
|
||||
$pattern1 \
|
||||
"step into vec_fun"
|
||||
|
||||
set pattern2 $pattern
|
||||
append pattern2 " at.*altivec-abi.c.*main.*result = vec_func .vshort,.*goes in v2.*Value returned is.*= .2, 2, 2, 2."
|
||||
|
||||
# Let's see if the result is returned correctly.
|
||||
gdb_test "finish" "Run till exit from .0.*$pattern2" \
|
||||
"vector value returned correctly"
|
||||
|
||||
# can we print the args correctly for this function?
|
||||
gdb_test "break struct_of_vector_func" "" ""
|
||||
|
||||
set pattern "struct_of_vector_func .vector_struct=.vshort1 = .1, 2, 3, 4, 5, 6, 7, 8., vshort2 = .11, 12, 13, 14, 15, 16, 17, 18., vshort3 = .21, 22, 23, 24, 25, 26, 27, 28., vshort4 = .31, 32, 33, 34, 35, 36, 37, 38... at.*altivec-abi.c.*"
|
||||
|
||||
gdb_test "continue" \
|
||||
"Breakpoint 3, $pattern.*vector_struct.vshort1 = vec_add .vector_struct.vshort1, vector_struct.vshort2.;" \
|
||||
"continue to struct_of_vector_func"
|
||||
|
||||
gdb_test "finish" \
|
||||
"Run till exit from .0 $pattern\[ \r\n\]+main.*altivec-abi.c.*array_of_vector_func.*" \
|
||||
"back to main (2)"
|
||||
|
||||
gdb_test "step" "" "step into array_of_vector_func"
|
||||
gdb_test "p matrix\[0\]" ".*= .1, 2, 3, 4, 5, 6, 7, 8." "print first vector"
|
||||
gdb_test "p matrix\[1\]" ".*= .11, 12, 13, 14, 15, 16, 17, 18." "print second vector"
|
||||
gdb_test "p matrix\[2\]" ".*= .21, 22, 23, 24, 25, 26, 27, 28." "print third vector"
|
||||
gdb_test "p matrix\[3\]" ".*= .31, 32, 33, 34, 35, 36, 37, 38." "print fourth vector"
|
||||
}
|
||||
|
||||
if [test_compiler_info gcc*] {
|
||||
set compile_flags "$compile_flags additional_flags=-maltivec additional_flags=-mabi=altivec"
|
||||
set saved_prefix $pf_prefix
|
||||
|
||||
set pf_prefix "${saved_prefix} default ABI, auto:"
|
||||
altivec_abi_tests "additional_flags=-maltivec" "auto"
|
||||
|
||||
# On GNU/Linux, we can mix -mabi=no-altivec and -mabi=altivec.
|
||||
# So test some combinations.
|
||||
if { [istarget "powerpc*-linux*"] } {
|
||||
set binfile ${objdir}/${subdir}/${testfile}-ge-ge
|
||||
set pf_prefix "${saved_prefix} generic ABI, forced:"
|
||||
altivec_abi_tests "additional_flags=-maltivec additional_flags=-mabi=no-altivec" "generic"
|
||||
|
||||
set binfile ${objdir}/${subdir}/${testfile}-av-av
|
||||
set pf_prefix "${saved_prefix} AltiVec ABI, forced:"
|
||||
altivec_abi_tests "additional_flags=-maltivec additional_flags=-mabi=altivec" "altivec"
|
||||
|
||||
set binfile ${objdir}/${subdir}/${testfile}-av-auto
|
||||
set pf_prefix "${saved_prefix} AltiVec ABI, auto:"
|
||||
altivec_abi_tests "additional_flags=-maltivec additional_flags=-mabi=altivec" "auto"
|
||||
}
|
||||
} elseif [test_compiler_info xlc*] {
|
||||
set compile_flags "$compile_flags additional_flags=-qaltivec"
|
||||
altivec_abi_tests "additional_flags=-qaltivec" "auto"
|
||||
} else {
|
||||
warning "unknown compiler"
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
|
||||
untested altivec-abi.exp
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
gdb_load ${binfile}
|
||||
|
||||
#
|
||||
# Run to `main' where we begin our tests.
|
||||
#
|
||||
|
||||
if ![runto_main] then {
|
||||
gdb_suppress_tests
|
||||
}
|
||||
|
||||
gdb_test "b marker" "Breakpoint 2 at.*file.*altivec-abi.c, line \[0-9\]+." "break marker"
|
||||
gdb_test "continue" "Breakpoint 2.*marker.*altivec-abi.c.*" "continue to marker"
|
||||
gdb_test "finish" "Run till exit from .0.*marker.*at.*altivec-abi.c.*main \\(\\) at.*altivec-abi.c.*result = vec_func \\(vshort,.*goes in v2.*" "back to main (1)"
|
||||
|
||||
# now all the arguments of vec_fun are initialized
|
||||
|
||||
set pattern "vec_func .vshort_f=.111, 222, 333, 444, 555, 666, 777, 888., vushort_f=.100, 200, 300, 400, 500, 600, 700, 800., vint_f=.-10, -20, -30, -40., vuint_f=.1111, 2222, 3333, 4444., vchar_f=.abcdefghilmnopqr., vuchar_f=.ABCDEFGHILMNOPQR., vfloat_f=.1.25, 3.75, 5.5, 1.25., x_f=.1, 2, 3, 4, 5, 6, 7, 8., y_f=.12, 22, 32, 42., a_f=.vector of chars.., b_f=.5.5, 4.5, 3.75, 2.25., c_f=.1.25, 3.5, 5.5, 7.75., intv_on_stack_f=.12, 34, 56, 78.."
|
||||
|
||||
set pattern1 $pattern
|
||||
append pattern1 " at.*altivec-abi.c.*vint_res = vec_add.*vint_f, intv_on_stack_f.;"
|
||||
|
||||
# Now let's call the function. This function has > 12 args,
|
||||
# the last one will go on the stack.
|
||||
gdb_test "p vec_func(vshort,vushort,vint,vuint,vchar,vuchar,vfloat,x,y,a,b,c,intv_on_stack)" \
|
||||
".\[0-9\]+ = .2, 2, 2, 2." "call inferior function with vectors (1) "
|
||||
|
||||
# Let's call the function again with dummy arguments. This is to clean
|
||||
# up the contents of the vector registers before the next call.
|
||||
gdb_test "p vec_func(vshort_d,vushort_d,vint_d,vuint_d,vchar_d,vuchar_d,vfloat_d,x_d,y_d,a_d,b_d,c_d,intv_on_stack_d)" \
|
||||
".\[0-9\]+ = .0, 0, 0, 0." "call inferior function with vectors (2) "
|
||||
|
||||
# Let's step into the function, to see if the args are printed correctly.
|
||||
gdb_test "step" \
|
||||
$pattern1 \
|
||||
"step into vec_fun"
|
||||
|
||||
set pattern2 $pattern
|
||||
append pattern2 " at.*altivec-abi.c.*main.*result = vec_func .vshort,.*goes in v2.*Value returned is.*= .2, 2, 2, 2."
|
||||
|
||||
# Let's see if the result is returned correctly.
|
||||
gdb_test "finish" \
|
||||
"Run till exit from .0.*$pattern2" \
|
||||
"vector value returned correctly"
|
||||
|
||||
# can we print the args correctly for this function?
|
||||
gdb_test "break struct_of_vector_func" "" ""
|
||||
|
||||
set pattern "struct_of_vector_func .vector_struct=.vshort1 = .1, 2, 3, 4, 5, 6, 7, 8., vshort2 = .11, 12, 13, 14, 15, 16, 17, 18., vshort3 = .21, 22, 23, 24, 25, 26, 27, 28., vshort4 = .31, 32, 33, 34, 35, 36, 37, 38... at.*altivec-abi.c.*"
|
||||
|
||||
gdb_test "continue" \
|
||||
"Breakpoint 3, $pattern.*vector_struct.vshort1 = vec_add .vector_struct.vshort1, vector_struct.vshort2.;" \
|
||||
"continue to struct_of_vector_func"
|
||||
|
||||
gdb_test "finish" \
|
||||
"Run till exit from .0 $pattern\[ \r\n\]+main.*altivec-abi.c.*array_of_vector_func.*" \
|
||||
"back to main (2)"
|
||||
|
||||
gdb_test "step" "" "step into array_of_vector_func"
|
||||
gdb_test "p matrix\[0\]" ".*= .1, 2, 3, 4, 5, 6, 7, 8." "print first vector"
|
||||
gdb_test "p matrix\[1\]" ".*= .11, 12, 13, 14, 15, 16, 17, 18." "print second vector"
|
||||
gdb_test "p matrix\[2\]" ".*= .21, 22, 23, 24, 25, 26, 27, 28." "print third vector"
|
||||
gdb_test "p matrix\[3\]" ".*= .31, 32, 33, 34, 35, 36, 37, 38." "print fourth vector"
|
||||
|
||||
|
|
Loading…
Reference in New Issue