+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
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
$(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) \
+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
@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.
@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}
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,
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
}
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. */
}
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
|| 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
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)
{
{
/* 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;
}
}
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)
{
}
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
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. */
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
}
-/* 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.,
/* 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) */
#include "libxcoff.h"
#include "elf-bfd.h"
+#include "elf/ppc.h"
#include "solib-svr4.h"
#include "ppc-tdep.h"
#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
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;
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;
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)
tdep = XCALLOC (1, struct gdbarch_tdep);
tdep->wordsize = wordsize;
+ tdep->soft_float = soft_float;
+ tdep->vector_abi = vector_abi;
gdbarch = gdbarch_alloc (&info, 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. */
extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
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);
}
+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
# 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
# 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."
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
}
-if [test_compiler_info gcc*] {
- set compile_flags "$compile_flags additional_flags=-maltivec additional_flags=-mabi=altivec"
-} elseif [test_compiler_info xlc*] {
- set compile_flags "$compile_flags additional_flags=-qaltivec"
-} else {
- warning "unknown compiler"
- return -1
-}
+proc altivec_abi_tests { extra_flags force_abi } {
+ global testfile binfile srcfile srcdir subdir
+ global gdb_prompt
-if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
- untested altivec-abi.exp
- return -1
-}
+ set compile_flags "debug nowarnings $extra_flags"
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
+ untested altivec-abi.exp
+ return -1
+ }
-#
-# Run to `main' where we begin our tests.
-#
+ 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 ![runto_main] then {
- gdb_suppress_tests
-}
+ 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 "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)"
+ gdb_test "set powerpc vector-abi $force_abi"
-# now all the arguments of vec_fun are initialized
+ 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)"
-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.."
+ # now all the arguments of vec_fun are initialized
-set pattern1 $pattern
-append pattern1 " at.*altivec-abi.c.*vint_res = vec_add.*vint_f, intv_on_stack_f.;"
+ 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.."
-# 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) "
+ set pattern1 $pattern
+ append pattern1 " at.*altivec-abi.c.*vint_res = vec_add.*vint_f, intv_on_stack_f.;"
-# 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) "
+ # 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 step into the function, to see if the args are printed correctly.
-gdb_test "step" \
- $pattern1 \
- "step into vec_fun"
+ # 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)"
-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 step into the function, to see if the args are printed correctly.
+ gdb_test "step" \
+ $pattern1 \
+ "step into vec_fun"
-# Let's see if the result is returned correctly.
-gdb_test "finish" \
- "Run till exit from .0.*$pattern2" \
- "vector value returned correctly"
+ set pattern2 $pattern
+ append pattern2 " at.*altivec-abi.c.*main.*result = vec_func .vshort,.*goes in v2.*Value returned is.*= .2, 2, 2, 2."
-# can we print the args correctly for this function?
-gdb_test "break struct_of_vector_func" "" ""
+ # Let's see if the result is returned correctly.
+ gdb_test "finish" "Run till exit from .0.*$pattern2" \
+ "vector value returned correctly"
-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.*"
+ # can we print the args correctly for this function?
+ gdb_test "break struct_of_vector_func" "" ""
-gdb_test "continue" \
- "Breakpoint 3, $pattern.*vector_struct.vshort1 = vec_add .vector_struct.vshort1, vector_struct.vshort2.;" \
- "continue to 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 "finish" \
- "Run till exit from .0 $pattern\[ \r\n\]+main.*altivec-abi.c.*array_of_vector_func.*" \
- "back to main (2)"
+ 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 "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"
+ 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 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*] {
+ altivec_abi_tests "additional_flags=-qaltivec" "auto"
+} else {
+ warning "unknown compiler"
+ return -1
+}