* 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>
* 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_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) \

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>
* gdb.texinfo (Files): Correct formatting. Mention Expat

View File

@ -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}

View File

@ -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.,

View File

@ -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) */

View File

@ -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);
}

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>
* 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
# 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"