* 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:
Daniel Jacobowitz 2007-10-30 19:35:35 +00:00
parent 7020f05c27
commit 55eddb0f7a
9 changed files with 431 additions and 105 deletions

View file

@ -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> 2007-10-29 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
* ppc-linux-tdep.c (ppc32_linux_reg_offsets): Corrected * ppc-linux-tdep.c (ppc32_linux_reg_offsets): Corrected

View file

@ -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_frv_h = $(INCLUDE_DIR)/elf/frv.h $(elf_reloc_macros_h)
elf_m32c_h = $(INCLUDE_DIR)/elf/m32c.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_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 libaout_h = $(BFD_SRC)/libaout.h
libiberty_h = $(INCLUDE_DIR)/libiberty.h libiberty_h = $(INCLUDE_DIR)/libiberty.h
libbfd_h = $(BFD_SRC)/libbfd.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) \ $(coff_xcoff_h) $(libxcoff_h) $(elf_bfd_h) $(solib_svr4_h) \
$(ppc_tdep_h) $(gdb_assert_h) $(dis_asm_h) $(trad_frame_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) \ $(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_32_c) $(powerpc_403_c) $(powerpc_403gc_c) $(powerpc_505_c) \
$(powerpc_601_c) $(powerpc_602_c) $(powerpc_603_c) $(powerpc_604_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) \ $(powerpc_64_c) $(powerpc_7400_c) $(powerpc_750_c) $(powerpc_860_c) \

View file

@ -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> 2007-10-24 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Files): Correct formatting. Mention Expat * gdb.texinfo (Files): Correct formatting. Mention Expat

View file

@ -14937,7 +14937,25 @@ Set suspend trace mode.
@node PowerPC @node PowerPC
@subsection PowerPC @subsection PowerPC
@value{GDBN} provides the following PowerPC-specific commands:
@table @code @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 @kindex target dink32
@item target dink32 @var{dev} @item target dink32 @var{dev}
DINK32 ROM monitor. DINK32 ROM monitor.
@ -14955,7 +14973,7 @@ SDS monitor, running on a PowerPC board (such as Motorola's ADS).
@cindex SDS protocol @cindex SDS protocol
The following commands specific to the SDS protocol are supported The following commands specific to the SDS protocol are supported
by@value{GDBN}: by @value{GDBN}:
@table @code @table @code
@item set sdstimeout @var{nsec} @item set sdstimeout @var{nsec}

View file

@ -104,8 +104,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
int len = TYPE_LENGTH (type); int len = TYPE_LENGTH (type);
const bfd_byte *val = value_contents (arg); const bfd_byte *val = value_contents (arg);
if (TYPE_CODE (type) == TYPE_CODE_FLT if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8
&& ppc_floating_point_unit_p (current_gdbarch) && len <= 8) && !tdep->soft_float)
{ {
/* Floating point value converted to "double" then /* Floating point value converted to "double" then
passed in an FP register, when the registers run out, 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; argoffset += 8;
} }
} }
else if (len == 8 && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */ else if (len == 8
|| (!ppc_floating_point_unit_p (current_gdbarch) && TYPE_CODE (type) == TYPE_CODE_FLT))) /* double */ && (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 pair with the low addressed word in the odd
register and the high addressed word in the even register and the high addressed word in the even
register, or when the registers run out an 8 byte 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 else if (len == 16
&& TYPE_CODE (type) == TYPE_CODE_ARRAY && 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 /* Vector parameter passed in an Altivec register, or
when that runs out, 16 byte aligned stack location. */ 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 else if (len == 8
&& TYPE_CODE (type) == TYPE_CODE_ARRAY && 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 /* Vector parameter passed in an e500 register, or when
that runs out, 8 byte aligned stack location. Note 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_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION) || TYPE_CODE (type) == TYPE_CODE_UNION)
{ {
/* Structs and large values are put on an 8 byte /* Structs and large values are put in an
aligned stack ... */ 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); structoffset = align_up (structoffset, 8);
if (write_pass) if (write_pass)
write_memory (sp + structoffset, val, len); write_memory (sp + structoffset, val, len);
/* ... and then a "word" pointing to that address is /* ... 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 static enum return_value_convention
do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
struct regcache *regcache, void *readbuf, struct regcache *regcache, gdb_byte *readbuf,
const void *writebuf, int broken_gcc) const gdb_byte *writebuf, int broken_gcc)
{ {
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (tdep->wordsize == 4); gdb_assert (tdep->wordsize == 4);
if (TYPE_CODE (type) == TYPE_CODE_FLT if (TYPE_CODE (type) == TYPE_CODE_FLT
&& TYPE_LENGTH (type) <= 8 && TYPE_LENGTH (type) <= 8
&& ppc_floating_point_unit_p (gdbarch)) && !tdep->soft_float)
{ {
if (readbuf) 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. */ /* A long long, or a double stored in the 32 bit r3/r4. */
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
(bfd_byte *) readbuf + 0); readbuf + 0);
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4, regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
(bfd_byte *) readbuf + 4); readbuf + 4);
} }
if (writebuf) if (writebuf)
{ {
/* A long long, or a double stored in the 32 bit r3/r4. */ /* A long long, or a double stored in the 32 bit r3/r4. */
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, 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, regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
(const bfd_byte *) writebuf + 4); writebuf + 4);
} }
return RETURN_VALUE_REGISTER_CONVENTION; 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 if (TYPE_LENGTH (type) == 16
&& TYPE_CODE (type) == TYPE_CODE_ARRAY && 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) if (readbuf)
{ {
@ -431,9 +441,42 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
} }
return RETURN_VALUE_REGISTER_CONVENTION; 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 if (TYPE_LENGTH (type) == 8
&& TYPE_CODE (type) == TYPE_CODE_ARRAY && 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 /* The e500 ABI places return values for the 64-bit DSP types
(__ev64_opaque__) in r3. However, in GDB-speak, ev3 (__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. */ the possible values of tdep->wordsize. */
gdb_assert (tdep->wordsize == 8); 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 /* By this stage in the proceedings, SP has been decremented by "red
zone size" + "struct return size". Fetch the stack-pointer from zone size" + "struct return size". Fetch the stack-pointer from
before this and use that as the BACK_CHAIN. */ 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. */ memory. */
if (write_pass) if (write_pass)
{ {
if (ppc_floating_point_unit_p (current_gdbarch) if (freg <= 13)
&& freg <= 13)
{ {
gdb_byte regval[MAX_REGISTER_SIZE]; gdb_byte regval[MAX_REGISTER_SIZE];
struct type *regtype 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 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., 0 if the return-value is instead stored on the stack (a.k.a.,

View file

@ -157,9 +157,24 @@ extern void ppc_collect_vrregset (const struct regset *regset,
/* Private data that this module attaches to struct gdbarch. */ /* 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 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_gp0_regnum; /* GPR register 0 */
int ppc_toc_regnum; /* TOC register */ int ppc_toc_regnum; /* TOC register */
int ppc_ps_regnum; /* Processor (or machine) status (%msr) */ int ppc_ps_regnum; /* Processor (or machine) status (%msr) */

View file

@ -49,6 +49,7 @@
#include "libxcoff.h" #include "libxcoff.h"
#include "elf-bfd.h" #include "elf-bfd.h"
#include "elf/ppc.h"
#include "solib-svr4.h" #include "solib-svr4.h"
#include "ppc-tdep.h" #include "ppc-tdep.h"
@ -77,6 +78,27 @@
#include "features/rs6000/powerpc-e500.c" #include "features/rs6000/powerpc-e500.c"
#include "features/rs6000/rs6000.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 /* If the kernel has to deliver a signal, it pushes a sigcontext
structure on the stack and then calls the signal handler, passing structure on the stack and then calls the signal handler, passing
the address of the sigcontext in an argument register. Usually 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; bfd abfd;
int sysv_abi; int sysv_abi;
asection *sect; 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 have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0;
int tdesc_wordsize = -1; int tdesc_wordsize = -1;
const struct target_desc *tdesc = info.target_desc; 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; 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. */ /* Find a candidate among extant architectures. */
for (arches = gdbarch_list_lookup_by_info (arches, &info); for (arches = gdbarch_list_lookup_by_info (arches, &info);
arches != NULL; 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 meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform
separate word size check. */ separate word size check. */
tdep = gdbarch_tdep (arches->gdbarch); 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 (tdep && tdep->wordsize == wordsize)
{ {
if (tdesc_data != NULL) 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 = XCALLOC (1, struct gdbarch_tdep);
tdep->wordsize = wordsize; tdep->wordsize = wordsize;
tdep->soft_float = soft_float;
tdep->vector_abi = vector_abi;
gdbarch = gdbarch_alloc (&info, tdep); gdbarch = gdbarch_alloc (&info, tdep);
@ -3643,6 +3744,61 @@ rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
/* FIXME: Dump gdbarch_tdep. */ /* 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. */ /* Initialization code. */
extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */ extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
@ -3668,4 +3824,30 @@ _initialize_rs6000_tdep (void)
initialize_tdesc_powerpc_860 (); initialize_tdesc_powerpc_860 ();
initialize_tdesc_powerpc_e500 (); initialize_tdesc_powerpc_e500 ();
initialize_tdesc_rs6000 (); 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);
} }

View file

@ -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> 2007-10-30 Pedro Alves <pedro_alves@portugalmail.pt>
* lib/gdb.exp, gdb.base/sepdebug.exp: Replace usage of eq and ne * lib/gdb.exp, gdb.base/sepdebug.exp: Replace usage of eq and ne

View file

@ -13,9 +13,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # 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 # Tests for Powerpc AltiVec ABI
@ -28,9 +25,6 @@ if $tracelevel then {
# This file uses altivec-abi.c for input. # This file uses altivec-abi.c for input.
# #
set prms_id 0
set bug_id 0
if {![istarget "powerpc*"] || [skip_altivec_tests]} then { if {![istarget "powerpc*"] || [skip_altivec_tests]} then {
verbose "Skipping altivec abi tests." verbose "Skipping altivec abi tests."
verbose -log "Skipping altivec abi tests." verbose -log "Skipping altivec abi tests."
@ -41,88 +35,124 @@ set testfile "altivec-abi"
set binfile ${objdir}/${subdir}/${testfile} set binfile ${objdir}/${subdir}/${testfile}
set srcfile ${testfile}.c set srcfile ${testfile}.c
set compile_flags {debug nowarnings}
if [get_compiler_info $binfile] { if [get_compiler_info $binfile] {
warning "get_compiler failed" warning "get_compiler failed"
return -1 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*] { 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*] { } elseif [test_compiler_info xlc*] {
set compile_flags "$compile_flags additional_flags=-qaltivec" altivec_abi_tests "additional_flags=-qaltivec" "auto"
} else { } else {
warning "unknown compiler" warning "unknown compiler"
return -1 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"