From 55eddb0f7a5dce5897c8f2128ba8cffb43531f0c Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Tue, 30 Oct 2007 19:35:35 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 22 +++ gdb/Makefile.in | 3 +- gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 20 ++- gdb/ppc-sysv-tdep.c | 91 ++++++++++--- gdb/ppc-tdep.h | 17 ++- gdb/rs6000-tdep.c | 182 +++++++++++++++++++++++++ gdb/testsuite/ChangeLog | 6 + gdb/testsuite/gdb.arch/altivec-abi.exp | 164 +++++++++++++--------- 9 files changed, 418 insertions(+), 92 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c356fb73f71..20aba85d202 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +2007-10-30 Daniel Jacobowitz + + * 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 * ppc-linux-tdep.c (ppc32_linux_reg_offsets): Corrected diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 52c6035bf28..79efa0d8f82 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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) \ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index d44a453097e..83d679fe2ac 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2007-10-30 Daniel Jacobowitz + + * gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set + powerpc soft-float". + 2007-10-24 Daniel Jacobowitz * gdb.texinfo (Files): Correct formatting. Mention Expat diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 7ad47fcab4e..83c768098ac 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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} diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 542acbd9909..5dc90f184ff 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -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., diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 62f0e7e1663..52b172f3864 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -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) */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index f133b78823a..0843be550c1 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -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); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 551c8d693b0..2f3a5d7c7c3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-10-30 Daniel Jacobowitz + + * 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 * lib/gdb.exp, gdb.base/sepdebug.exp: Replace usage of eq and ne diff --git a/gdb/testsuite/gdb.arch/altivec-abi.exp b/gdb/testsuite/gdb.arch/altivec-abi.exp index bdb7853831f..c811c3d637a 100644 --- a/gdb/testsuite/gdb.arch/altivec-abi.exp +++ b/gdb/testsuite/gdb.arch/altivec-abi.exp @@ -13,9 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -# 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 } -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 +} -- 2.30.2