summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena Zannoni <ezannoni@kwikemart.cygnus.com>2002-04-29 15:10:06 +0000
committerElena Zannoni <ezannoni@kwikemart.cygnus.com>2002-04-29 15:10:06 +0000
commit87e025ec8568c0afd976b12794cc0aa2c10db8bc (patch)
tree6bba347c6c0f9496fc1f87530ddf61e8bc04a4e3
parent222f22005481d084def8a13db673e01406c9cd50 (diff)
downloadgdb-87e025ec8568c0afd976b12794cc0aa2c10db8bc.tar.gz
2002-04-29 Elena Zannoni <ezannoni@redhat.com>
* rs6000-tdep.c (rs6000_extract_return_value, rs6000_store_return_value): Handle returning vectors. (rs6000_gdbarch_init): Use ppc_sysv_abi_broken_use_struct_convention for native sysv cases. * ppc-linux-tdep.c (ppc_sysv_abi_broken_use_struct_convention): New function. (ppc_sysv_abi_use_struct_convention): Deal with functions returning vectors. (ppc_sysv_abi_push_arguments): Handle vector parameters. * ppc-tdep.h (ppc_sysv_abi_broken_use_struct_convention): Export.
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/ppc-linux-tdep.c81
-rw-r--r--gdb/ppc-tdep.h1
-rw-r--r--gdb/rs6000-tdep.c19
4 files changed, 110 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6499ae9444b..a5e4e951b16 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -36,6 +36,24 @@
2002-04-26 Elena Zannoni <ezannoni@redhat.com>
+ * rs6000-tdep.c (rs6000_extract_return_value,
+ rs6000_store_return_value): Handle returning vectors.
+ (rs6000_gdbarch_init): Use
+ ppc_sysv_abi_broken_use_struct_convention for native sysv cases.
+ * ppc-linux-tdep.c (ppc_sysv_abi_broken_use_struct_convention):
+ New function.
+ (ppc_sysv_abi_use_struct_convention): Deal with functions returning
+ vectors.
+ (ppc_sysv_abi_push_arguments): Handle vector parameters.
+ * ppc-tdep.h (ppc_sysv_abi_broken_use_struct_convention): Export.
+
+2002-04-26 Elena Zannoni <ezannoni@redhat.com>
+
+ * Makefile.in (thread-db.o): This file cannot be built with
+ ,-Werror enabled.
+
+2002-04-26 Elena Zannoni <ezannoni@redhat.com>
+
* gdbtypes.h (TYPE_FLAG_VECTOR, TYPE_VECTOR): Define.
* gdbtypes.c (recursive_dump_type): Output the vector flag.
* dwarf2read.c (dwarf_attr_name): Handle new attribute for
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index bd765990cf3..f358274140b 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -415,11 +415,29 @@ ppc_linux_frame_chain (struct frame_info *thisframe)
it may be used generically by ports which use either the SysV ABI or
the EABI */
+/* Until November 2001, gcc was not complying to the SYSV ABI for
+ returning structures less than or equal to 8 bytes in size. It was
+ returning everything in memory. When this was corrected, it wasn't
+ fixed for native platforms. */
+int
+ppc_sysv_abi_broken_use_struct_convention (int gcc_p, struct type *value_type)
+{
+ if (TYPE_LENGTH (value_type) == 16
+ && TYPE_VECTOR (value_type))
+ return 0;
+
+ return generic_use_struct_convention (gcc_p, value_type);
+}
+
/* Structures 8 bytes or less long are returned in the r3 & r4
registers, according to the SYSV ABI. */
int
ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type)
{
+ if (TYPE_LENGTH (value_type) == 16
+ && TYPE_VECTOR (value_type))
+ return 0;
+
return (TYPE_LENGTH (value_type) > 8);
}
@@ -445,7 +463,12 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
int argno;
- int greg, freg;
+ /* Next available general register for non-float, non-vector arguments. */
+ int greg;
+ /* Next available floating point register for float arguments. */
+ int freg;
+ /* Next available vector register for vector arguments. */
+ int vreg;
int argstkspace;
int structstkspace;
int argoffset;
@@ -458,6 +481,7 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
greg = struct_return ? 4 : 3;
freg = 1;
+ vreg = 2;
argstkspace = 0;
structstkspace = 0;
@@ -500,21 +524,38 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
greg += 2;
}
}
- else
- {
+ else if (!TYPE_VECTOR (type))
+ {
if (len > 4
|| TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION)
{
/* Rounding to the nearest multiple of 8 may not be necessary,
- but it is safe. Particularly since we don't know the
- field types of the structure */
+ but it is safe. Particularly since we don't know the
+ field types of the structure */
structstkspace += round2 (len, 8);
}
if (greg <= 10)
greg++;
else
argstkspace += 4;
+ }
+ else
+ {
+ if (len == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type))
+ {
+ if (vreg <= 13)
+ vreg++;
+ else
+ {
+ /* Vector arguments must be aligned to 16 bytes on
+ the stack. */
+ argstkspace += round2 (argstkspace, 16);
+ argstkspace += 16;
+ }
+ }
}
}
@@ -540,6 +581,7 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
structoffset = argoffset + argstkspace;
freg = 1;
greg = 3;
+ vreg = 2;
/* Fill in r3 with the return structure, if any */
if (struct_return)
{
@@ -561,7 +603,7 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
{
if (len > 8)
printf_unfiltered (
- "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+ "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM + freg)],
VALUE_CONTENTS (arg), len);
freg++;
@@ -599,7 +641,7 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
greg += 2;
}
}
- else
+ else if (!TYPE_VECTOR (type))
{
char val_buf[4];
if (len > 4
@@ -617,7 +659,6 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
}
if (greg <= 10)
{
- *(int *) &registers[REGISTER_BYTE (greg)] = 0;
memcpy (&registers[REGISTER_BYTE (greg)], val_buf, 4);
greg++;
}
@@ -627,6 +668,30 @@ ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
argoffset += 4;
}
}
+ else
+ {
+ if (len == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type))
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ char *v_val_buf = alloca (16);
+ memset (v_val_buf, 0, 16);
+ memcpy (v_val_buf, VALUE_CONTENTS (arg), len);
+ if (vreg <= 13)
+ {
+ memcpy (&registers[REGISTER_BYTE (tdep->ppc_vr0_regnum
+ + vreg)],
+ v_val_buf, 16);
+ vreg++;
+ }
+ else
+ {
+ write_memory (sp + argoffset, v_val_buf, 16);
+ argoffset += 16;
+ }
+ }
+ }
}
target_store_registers (-1);
diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h
index 5dc2db25d36..3da66ad1405 100644
--- a/gdb/ppc-tdep.h
+++ b/gdb/ppc-tdep.h
@@ -32,6 +32,7 @@ int ppc_linux_frameless_function_invocation (struct frame_info *);
void ppc_linux_frame_init_saved_regs (struct frame_info *);
CORE_ADDR ppc_linux_frame_chain (struct frame_info *);
int ppc_sysv_abi_use_struct_convention (int, struct type *);
+int ppc_sysv_abi_broken_use_struct_convention (int, struct type *);
CORE_ADDR ppc_sysv_abi_push_arguments (int, struct value **, CORE_ADDR, int,
CORE_ADDR);
int ppc_linux_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache);
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 97b936dd873..8ccfb99efe5 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1144,6 +1144,7 @@ static void
rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
{
int offset = 0;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
{
@@ -1165,6 +1166,13 @@ rs6000_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
memcpy (valbuf, &ff, sizeof (float));
}
}
+ else if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+ && TYPE_LENGTH (valtype) == 16
+ && TYPE_VECTOR (valtype))
+ {
+ memcpy (valbuf, regbuf + REGISTER_BYTE (tdep->ppc_vr0_regnum + 2),
+ TYPE_LENGTH (valtype));
+ }
else
{
/* return value is copied starting from r3. */
@@ -1909,6 +1917,8 @@ rs6000_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
static void
rs6000_store_return_value (struct type *type, char *valbuf)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
if (TYPE_CODE (type) == TYPE_CODE_FLT)
/* Floating point values are returned starting from FPR1 and up.
@@ -1917,6 +1927,13 @@ rs6000_store_return_value (struct type *type, char *valbuf)
write_register_bytes (REGISTER_BYTE (FP0_REGNUM + 1), valbuf,
TYPE_LENGTH (type));
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ if (TYPE_LENGTH (type) == 16
+ && TYPE_VECTOR (type))
+ write_register_bytes (REGISTER_BYTE (tdep->ppc_vr0_regnum + 2),
+ valbuf, TYPE_LENGTH (type));
+ }
else
/* Everything else is returned in GPR3 and up. */
write_register_bytes (REGISTER_BYTE (gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3),
@@ -2706,7 +2723,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|| osabi == ELFOSABI_NETBSD
|| osabi == ELFOSABI_FREEBSD)
set_gdbarch_use_struct_convention (gdbarch,
- generic_use_struct_convention);
+ ppc_sysv_abi_broken_use_struct_convention);
else
set_gdbarch_use_struct_convention (gdbarch,
ppc_sysv_abi_use_struct_convention);