* [rfa?] Implement ppc32 SYSV {extract,store} return value
@ 2003-09-17 21:54 Andrew Cagney
2003-09-22 21:58 ` Kevin Buettner
0 siblings, 1 reply; 11+ messages in thread
From: Andrew Cagney @ 2003-09-17 21:54 UTC (permalink / raw)
To: gdb-patches, Kevin Buettner, Jason R Thorpe
[-- Attachment #1: Type: text/plain, Size: 769 bytes --]
Hello,
This adds a new ppc32 SYSV specific extract_return_value and
store_return_value (while at the same time eliminating the e500 specific
methods). The new functions also avoid some really bogus looking
floating point code in the old rs6000 * return_value functions - I'm
still trying to figure out how it worked ... ah, it's native only.
I've tested it in vanila GNU/Linux (no regressions) and NBSD (4 less
structs fails) (i.e., no altivec nor e500).
If nothing else I'd really like a comment on the general approach taken
- the netbsd function wrapping a more generic method, and a better word
than "broken" I guess.
thoughts?
Andrew
PS: My comments refer to SYSV ppc32 but the change does also affect SYSV
ppc64, "can I get back to you on that" :-)
[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 17703 bytes --]
2003-09-13 Andrew Cagney <cagney@redhat.com>
* rs6000-tdep.c (e500_store_return_value): Delete function.
(e500_extract_return_value): Delete function.
(rs6000_gdbarch_init): When SYSV, set "extract_return_value" and
"restore_return_value" to "ppc_sysv_abi_extract_return_value" and
"ppc_sysv_abi_restore_return_value" where applicable.
* ppc-tdep.h: Re-organize so that functions from "ppc-sysv-tdep.c"
are all the one place.
(ppc_sysv_abi_store_return_value): Declare.
(ppc_sysv_abi_extract_return_value): Declare.
(ppc_sysv_abi_broken_store_return_value): Declare.
(ppc_sysv_abi_broken_extract_return_value): Declare.
* ppc-sysv-tdep.c (extract_return_value): New function.
(store_return_value): New function.
(ppc_sysv_abi_extract_return_value): New function.
(ppc_sysv_abi_store_return_value): New function.
(ppc_sysv_abi_broken_extract_return_value): New function.
(ppc_sysv_abi_broken_store_return_value): New function.
Index: ppc-sysv-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.11
diff -u -r1.11 ppc-sysv-tdep.c
--- ppc-sysv-tdep.c 16 Sep 2003 23:33:17 -0000 1.11
+++ ppc-sysv-tdep.c 17 Sep 2003 21:22:27 -0000
@@ -340,3 +340,228 @@
return (TYPE_LENGTH (value_type) > 8);
}
+
+static void
+extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf, int broken)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ if (using_struct_return (type, 1))
+ error ("Function return value unknown");
+ else if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) <= 8
+ && ppc_floating_point_unit_p (current_gdbarch))
+ {
+ /* Floats and doubles stored in "f1". Convert the value to the
+ required type. */
+ char regval[MAX_REGISTER_SIZE];
+ struct type *regtype = register_type (current_gdbarch, FP0_REGNUM + 1);
+ regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
+ convert_typed_floating (regval, regtype, valbuf, type);
+ }
+ else if ((TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4)
+ || (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4))
+ {
+ /* A long long, or a double stored in r3/r4. */
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ (bfd_byte *) valbuf + 0);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ (bfd_byte *) valbuf + 4);
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) <= tdep->wordsize)
+ {
+ /* Some sort of integer stored in r3. Since TYPE isn't bigger
+ than the register, sign extension isn't a problem - just do
+ everything unsigned. */
+ ULONGEST regval;
+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+ ®val);
+ store_unsigned_integer (valbuf, TYPE_LENGTH (type), regval);
+ }
+ else if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_vr0_regnum >= 0)
+ {
+ /* Altivec places the return value in "v2". */
+ regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, valbuf);
+ }
+ else if (TYPE_LENGTH (type) == 8
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_ev0_regnum >= 0)
+ {
+ /* e500 places the return value in "ev2". */
+ regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 2, valbuf);
+ }
+ else if (broken && TYPE_LENGTH (type) <= 8)
+ {
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each register
+ and then store that. */
+ /* Transfer any full words. */
+ int word = 0;
+ while (1)
+ {
+ ULONGEST reg;
+ int len = TYPE_LENGTH (type) - word * tdep->wordsize;
+ if (len <= 0)
+ break;
+ if (len > tdep->wordsize)
+ len = tdep->wordsize;
+ regcache_cooked_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + 3 + word,
+ ®);
+ store_unsigned_integer ((bfd_byte *) valbuf + word * tdep->wordsize,
+ len, reg);
+ word++;
+ }
+ }
+ else if (TYPE_LENGTH (type) <= 8)
+ {
+ /* This matches SVr4 PPC, it does not match gcc. */
+ /* The value is padded out to 8 bytes and then loaded, as two
+ "words" into r3/r3. */
+ char regvals[MAX_REGISTER_SIZE * 2];
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (TYPE_LENGTH (type) > tdep->wordsize)
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ memcpy (valbuf, regvals, TYPE_LENGTH (type));
+ }
+ else
+ internal_error (__FILE__, __LINE__, "return type unhandled");
+}
+
+void
+ppc_sysv_abi_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf)
+{
+ extract_return_value (type, regcache, valbuf, 0);
+}
+
+void
+ppc_sysv_abi_broken_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf)
+{
+ extract_return_value (type, regcache, valbuf, 1);
+}
+
+static void
+store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf, int broken)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ if (using_struct_return (type, 1))
+ error ("Cannot return value");
+ else if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) <= 8
+ && ppc_floating_point_unit_p (current_gdbarch))
+ {
+ /* Floats and doubles stored in "f1". Convert the value to the
+ register's "double" type. */
+ char regval[MAX_REGISTER_SIZE];
+ struct type *regtype = register_type (current_gdbarch, FP0_REGNUM + 1);
+ convert_typed_floating (valbuf, type, regval, regtype);
+ regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
+ }
+ else if ((TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4)
+ || (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4))
+ {
+ /* A long long, or a double stored in r3/r4. */
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ (bfd_byte *) valbuf + 0);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ (bfd_byte *) valbuf + 4);
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) <= tdep->wordsize)
+ {
+ /* Some sort of integer stored in r3. Use unpack_long since
+ that should handle any required sign extension. */
+ regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+ unpack_long (type, valbuf));
+ }
+ else if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_vr0_regnum >= 0)
+ {
+ /* Altivec places the return value in "v2". */
+ regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, valbuf);
+ }
+ else if (TYPE_LENGTH (type) == 8
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_ev0_regnum >= 0)
+ {
+ /* e500 places the return value in "ev2". */
+ regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 2, valbuf);
+ }
+ else if (broken && TYPE_LENGTH (type) <= 8)
+ {
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each register
+ and then store that. */
+ /* Transfer any full words. */
+ int word = 0;
+ while (1)
+ {
+ ULONGEST reg;
+ int len = TYPE_LENGTH (type) - word * tdep->wordsize;
+ if (len <= 0)
+ break;
+ if (len > tdep->wordsize)
+ len = tdep->wordsize;
+ reg = extract_unsigned_integer ((bfd_byte *) valbuf + word * tdep->wordsize, len);
+ regcache_cooked_write_unsigned (regcache,
+ tdep->ppc_gp0_regnum + 3 + word,
+ reg);
+ word++;
+ }
+ }
+ else if (TYPE_LENGTH (type) <= 8)
+ {
+ /* This matches SVr4 PPC, it does not match gcc. */
+ /* The value is padded out to 8 bytes and then loaded, as two
+ "words" into r3/r3. */
+ char regvals[MAX_REGISTER_SIZE * 2];
+ memset (regvals, 0, sizeof regvals);
+ memcpy (regvals, valbuf, TYPE_LENGTH (type));
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (TYPE_LENGTH (type) > tdep->wordsize)
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ }
+ else
+ internal_error (__FILE__, __LINE__, "return type unhandled");
+}
+
+void
+ppc_sysv_abi_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
+{
+ store_return_value (type, regcache, valbuf, 0);
+}
+
+void
+ppc_sysv_abi_broken_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf)
+{
+ store_return_value (type, regcache, valbuf, 1);
+}
Index: ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.18
diff -u -r1.18 ppc-tdep.h
--- ppc-tdep.h 14 Sep 2003 02:04:44 -0000 1.18
+++ ppc-tdep.h 17 Sep 2003 21:22:27 -0000
@@ -33,20 +33,36 @@
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_dummy_call (struct gdbarch *gdbarch,
- CORE_ADDR func_addr,
- struct regcache *regcache,
- CORE_ADDR bp_addr, int nargs,
- struct value **args, CORE_ADDR sp,
- int struct_return,
- CORE_ADDR struct_addr);
int ppc_linux_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache);
struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void);
void ppc_linux_supply_gregset (char *buf);
void ppc_linux_supply_fpregset (char *buf);
+
+/* From ppc-sysv-tdep.c... */
+extern CORE_ADDR ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+ CORE_ADDR func_addr,
+ struct regcache *regcache,
+ CORE_ADDR bp_addr, int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ int struct_return,
+ CORE_ADDR struct_addr);
+
+extern int ppc_sysv_abi_use_struct_convention (int, struct type *);
+extern void ppc_sysv_abi_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf);
+extern void ppc_sysv_abi_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf);
+
+extern void ppc_sysv_abi_broken_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf);
+extern void ppc_sysv_abi_broken_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf);
/* From rs6000-tdep.c... */
CORE_ADDR rs6000_frame_saved_pc (struct frame_info *fi);
Index: ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.8
diff -u -r1.8 ppcnbsd-tdep.c
--- ppcnbsd-tdep.c 17 Sep 2003 20:10:48 -0000 1.8
+++ ppcnbsd-tdep.c 17 Sep 2003 21:22:27 -0000
@@ -204,6 +204,7 @@
return (nbsd_pc_in_sigtramp (pc, func_name));
}
+
/* NetBSD is confused. It appears that 1.5 was using the correct SVr4
convention but, 1.6 switched to the below broken convention. For
the moment use the broken convention. Ulgh!. */
@@ -226,8 +227,11 @@
struct gdbarch *gdbarch)
{
set_gdbarch_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
-
+ /* For NetBSD, this is an on again, off again thing. Some systems
+ do use the broken struct convention, and some don't. */
set_gdbarch_use_struct_convention (gdbarch, ppcnbsd_use_struct_convention);
+ set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_broken_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_broken_store_return_value);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
}
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.161
diff -u -r1.161 rs6000-tdep.c
--- rs6000-tdep.c 17 Sep 2003 14:24:30 -0000 1.161
+++ rs6000-tdep.c 17 Sep 2003 21:22:28 -0000
@@ -1313,65 +1313,6 @@
return sp;
}
-/* Extract a function return value of type TYPE from raw register array
- REGBUF, and copy that return value into VALBUF in virtual format. */
-static void
-e500_extract_return_value (struct type *valtype, struct regcache *regbuf, void *valbuf)
-{
- int offset = 0;
- int vallen = TYPE_LENGTH (valtype);
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
- && vallen == 8
- && TYPE_VECTOR (valtype))
- {
- regcache_raw_read (regbuf, tdep->ppc_ev0_regnum + 3, valbuf);
- }
- else
- {
- /* Return value is copied starting from r3. Note that r3 for us
- is a pseudo register. */
- int offset = 0;
- int return_regnum = tdep->ppc_gp0_regnum + 3;
- int reg_size = REGISTER_RAW_SIZE (return_regnum);
- int reg_part_size;
- char *val_buffer;
- int copied = 0;
- int i = 0;
-
- /* Compute where we will start storing the value from. */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- {
- if (vallen <= reg_size)
- offset = reg_size - vallen;
- else
- offset = reg_size + (reg_size - vallen);
- }
-
- /* How big does the local buffer need to be? */
- if (vallen <= reg_size)
- val_buffer = alloca (reg_size);
- else
- val_buffer = alloca (vallen);
-
- /* Read all we need into our private buffer. We copy it in
- chunks that are as long as one register, never shorter, even
- if the value is smaller than the register. */
- while (copied < vallen)
- {
- reg_part_size = REGISTER_RAW_SIZE (return_regnum + i);
- /* It is a pseudo/cooked register. */
- regcache_cooked_read (regbuf, return_regnum + i,
- val_buffer + copied);
- copied += reg_part_size;
- i++;
- }
- /* Put the stuff in the return buffer. */
- memcpy (valbuf, val_buffer + offset, vallen);
- }
-}
-
/* PowerOpen always puts structures in memory. Vectors, which were
added later, do get returned in a register though. */
@@ -2046,30 +1987,6 @@
return regnum;
}
-/* Write into appropriate registers a function return value
- of type TYPE, given in virtual format. */
-static void
-e500_store_return_value (struct type *type, char *valbuf)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- /* Everything is returned in GPR3 and up. */
- int copied = 0;
- int i = 0;
- int len = TYPE_LENGTH (type);
- while (copied < len)
- {
- int regnum = gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3 + i;
- int reg_size = REGISTER_RAW_SIZE (regnum);
- char *reg_val_buf = alloca (reg_size);
-
- memcpy (reg_val_buf, valbuf + copied, reg_size);
- copied += reg_size;
- deprecated_write_register_gen (regnum, reg_val_buf);
- i++;
- }
-}
-
static void
rs6000_store_return_value (struct type *type, char *valbuf)
{
@@ -2830,9 +2747,6 @@
set_gdbarch_pc_regnum (gdbarch, 64);
set_gdbarch_sp_regnum (gdbarch, 1);
set_gdbarch_deprecated_fp_regnum (gdbarch, 1);
- set_gdbarch_deprecated_extract_return_value (gdbarch,
- rs6000_extract_return_value);
- set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value);
if (v->arch == bfd_arch_powerpc)
switch (v->mach)
@@ -2866,8 +2780,6 @@
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
- set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value);
- set_gdbarch_deprecated_store_return_value (gdbarch, e500_store_return_value);
break;
default:
tdep->ppc_vr0_regnum = -1;
@@ -2965,11 +2877,17 @@
set_gdbarch_frame_args_skip (gdbarch, 8);
if (sysv_abi)
- set_gdbarch_use_struct_convention (gdbarch,
- ppc_sysv_abi_use_struct_convention);
+ {
+ set_gdbarch_use_struct_convention (gdbarch, ppc_sysv_abi_use_struct_convention);
+ set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_store_return_value);
+ }
else
- set_gdbarch_use_struct_convention (gdbarch,
- rs6000_use_struct_convention);
+ {
+ set_gdbarch_use_struct_convention (gdbarch, rs6000_use_struct_convention);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value);
+ }
set_gdbarch_frameless_function_invocation (gdbarch,
rs6000_frameless_function_invocation);
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-09-17 21:54 [rfa?] Implement ppc32 SYSV {extract,store} return value Andrew Cagney
@ 2003-09-22 21:58 ` Kevin Buettner
2003-10-04 17:43 ` Andrew Cagney
0 siblings, 1 reply; 11+ messages in thread
From: Kevin Buettner @ 2003-09-22 21:58 UTC (permalink / raw)
To: Andrew Cagney, gdb-patches, Kevin Buettner, Jason R Thorpe
On Sep 17, 5:54pm, Andrew Cagney wrote:
> If nothing else I'd really like a comment on the general approach taken
> - the netbsd function wrapping a more generic method,
What are you referring to here? I looked at the netbsd portion of
your patch and I don't see what you're referring to. I do see
that your using the ppc_sys_v_abi_... version for extract_return_value
and store_return_value. But I think that's okay until we find that
it's broken in ways not already handled by the code you've just added.
(This is different than the case that I commented on previously -- In
which it appeared that code for one ABI was reusable by another. In
such a case, I think clearly distinguishing the code implementing the
two ABIs is a good idea. For NetBSD, it's supposed to be implementing
the System V ABI, right? That being the case, I think it's just fine
to do things the way you've arranged it.)
> and a better word than "broken" I guess.
At the moment, I can't think of anything better. (Or, to put it another
way, anything that I've thought of ends up being overly verbose.)
Anyway, your patch looks okay to me. Feel free to check it in.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-09-22 21:58 ` Kevin Buettner
@ 2003-10-04 17:43 ` Andrew Cagney
2003-10-06 19:12 ` Kevin Buettner
0 siblings, 1 reply; 11+ messages in thread
From: Andrew Cagney @ 2003-10-04 17:43 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches, Jason R Thorpe
[-- Attachment #1: Type: text/plain, Size: 1363 bytes --]
> On Sep 17, 5:54pm, Andrew Cagney wrote:
>
>
>> If nothing else I'd really like a comment on the general approach taken
>> - the netbsd function wrapping a more generic method,
>
>
> What are you referring to here? I looked at the netbsd portion of
> your patch and I don't see what you're referring to. I do see
> that your using the ppc_sys_v_abi_... version for extract_return_value
> and store_return_value. But I think that's okay until we find that
> it's broken in ways not already handled by the code you've just added.
Just that. Wrapping the more generic method.
> (This is different than the case that I commented on previously -- In
> which it appeared that code for one ABI was reusable by another. In
> such a case, I think clearly distinguishing the code implementing the
> two ABIs is a good idea. For NetBSD, it's supposed to be implementing
> the System V ABI, right? That being the case, I think it's just fine
> to do things the way you've arranged it.)
>
>
>> and a better word than "broken" I guess.
>
>
> At the moment, I can't think of anything better. (Or, to put it another
> way, anything that I've thought of ends up being overly verbose.)
>
> Anyway, your patch looks okay to me. Feel free to check it in.
Here is a revised version. It's now implemented using a wrapped
..._return_value.
Still ok?
Andrew
[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 17097 bytes --]
2003-10-03 Andrew Cagney <cagney@redhat.com>
* rs6000-tdep.c (e500_store_return_value): Delete function.
(e500_extract_return_value): Delete function.
(rs6000_gdbarch_init): When SYSV, set "extract_return_value" and
"restore_return_value" to "ppc_sysv_abi_extract_return_value" and
"ppc_sysv_abi_restore_return_value" where applicable.
* ppc-tdep.h: (ppc_sysv_abi_store_return_value): Declare.
(ppc_sysv_abi_extract_return_value): Declare.
(ppc_sysv_abi_broken_store_return_value): Declare.
(ppc_sysv_abi_broken_extract_return_value): Declare.
(ppc_sysv_abi_broken_use_struct_convention:) Delete declaration.
* ppc-sysv-tdep.c (do_ppc_sysv_return_value): New function.
(ppc_sysv_abi_extract_return_value): New function.
(ppc_sysv_abi_store_return_value): New function.
(ppc_sysv_abi_broken_extract_return_value): New function.
(ppc_sysv_abi_broken_store_return_value): New function.
(ppc_sysv_abi_use_struct_convention): Call
do_ppc_sysv_return_value.
Index: ppc-sysv-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.13
diff -u -r1.13 ppc-sysv-tdep.c
--- ppc-sysv-tdep.c 3 Oct 2003 21:11:39 -0000 1.13
+++ ppc-sysv-tdep.c 4 Oct 2003 17:42:27 -0000
@@ -314,16 +314,256 @@
return sp;
}
+/* Potential ways that a function can return a value of a given type. */
+enum return_value_convention
+{
+ /* Where the return value has been squeezed into one or more
+ registers. */
+ RETURN_VALUE_REGISTER_CONVENTION,
+ /* Commonly known as the "struct return convention". The caller
+ passes an additional hidden first parameter to the caller. That
+ parameter contains the address at which the value being returned
+ should be stored. While typically, and historically, used for
+ large structs, this is convention is applied to values of many
+ different types. */
+ RETURN_VALUE_STRUCT_CONVENTION
+};
+
+static enum return_value_convention
+do_ppc_sysv_return_value (struct type *type, struct regcache *regcache,
+ const void *inval, void *outval, int broken)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) <= 8
+ && ppc_floating_point_unit_p (current_gdbarch))
+ {
+ if (outval)
+ {
+ /* Floats and doubles stored in "f1". Convert the value to
+ the required type. */
+ char regval[MAX_REGISTER_SIZE];
+ struct type *regtype = register_type (current_gdbarch,
+ FP0_REGNUM + 1);
+ regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
+ convert_typed_floating (regval, regtype, outval, type);
+ }
+ if (inval)
+ {
+ /* Floats and doubles stored in "f1". Convert the value to
+ the register's "double" type. */
+ char regval[MAX_REGISTER_SIZE];
+ struct type *regtype = register_type (current_gdbarch, FP0_REGNUM);
+ convert_typed_floating (inval, type, regval, regtype);
+ regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if ((TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4)
+ || (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4))
+ {
+ if (outval)
+ {
+ /* A long long, or a double stored in the 32 bit r3/r4. */
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ (bfd_byte *) outval + 0);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ (bfd_byte *) outval + 4);
+ }
+ if (inval)
+ {
+ /* A long long, or a double stored in the 32 bit r3/r4. */
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ (bfd_byte *) inval + 0);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ (bfd_byte *) inval + 4);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) <= tdep->wordsize)
+ {
+ if (outval)
+ {
+ /* Some sort of integer stored in r3. Since TYPE isn't
+ bigger than the register, sign extension isn't a problem
+ - just do everything unsigned. */
+ ULONGEST regval;
+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+ ®val);
+ store_unsigned_integer (outval, TYPE_LENGTH (type), regval);
+ }
+ if (inval)
+ {
+ /* Some sort of integer stored in r3. Use unpack_long since
+ that should handle any required sign extension. */
+ regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+ unpack_long (type, inval));
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_vr0_regnum >= 0)
+ {
+ if (outval)
+ {
+ /* Altivec places the return value in "v2". */
+ regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, outval);
+ }
+ if (inval)
+ {
+ /* Altivec places the return value in "v2". */
+ regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, inval);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_LENGTH (type) == 8
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_ev0_regnum >= 0)
+ {
+ if (outval)
+ {
+ /* e500 places the return value in "ev2". */
+ regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 2, outval);
+ }
+ if (inval)
+ {
+ /* e500 places the return value in "ev2". */
+ regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 2, inval);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (broken && TYPE_LENGTH (type) <= 8)
+ {
+ if (outval)
+ {
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each
+ register and then store that. */
+ /* Transfer any full words. */
+ int word = 0;
+ while (1)
+ {
+ ULONGEST reg;
+ int len = TYPE_LENGTH (type) - word * tdep->wordsize;
+ if (len <= 0)
+ break;
+ if (len > tdep->wordsize)
+ len = tdep->wordsize;
+ regcache_cooked_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + 3 + word,
+ ®);
+ store_unsigned_integer (((bfd_byte *) outval
+ + word * tdep->wordsize),
+ len, reg);
+ word++;
+ }
+ }
+ if (inval)
+ {
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each
+ register and then store that. */
+ /* Transfer any full words. */
+ int word = 0;
+ while (1)
+ {
+ ULONGEST reg;
+ int len = TYPE_LENGTH (type) - word * tdep->wordsize;
+ if (len <= 0)
+ break;
+ if (len > tdep->wordsize)
+ len = tdep->wordsize;
+ reg = extract_unsigned_integer (((bfd_byte *) inval
+ + word * tdep->wordsize),
+ len);
+ regcache_cooked_write_unsigned (regcache,
+ tdep->ppc_gp0_regnum + 3 + word,
+ reg);
+ word++;
+ }
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_LENGTH (type) <= 8)
+ {
+ if (outval)
+ {
+ /* This matches SVr4 PPC, it does not match gcc. */
+ /* The value is padded out to 8 bytes and then loaded, as
+ two "words" into r3/r3. */
+ char regvals[MAX_REGISTER_SIZE * 2];
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (TYPE_LENGTH (type) > tdep->wordsize)
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ memcpy (outval, regvals, TYPE_LENGTH (type));
+ }
+ if (inval)
+ {
+ /* This matches SVr4 PPC, it does not match gcc. */
+ /* The value is padded out to 8 bytes and then loaded, as
+ two "words" into r3/r3. */
+ char regvals[MAX_REGISTER_SIZE * 2];
+ memset (regvals, 0, sizeof regvals);
+ memcpy (regvals, inval, TYPE_LENGTH (type));
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (TYPE_LENGTH (type) > tdep->wordsize)
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ return RETURN_VALUE_STRUCT_CONVENTION;
+}
+
+void
+ppc_sysv_abi_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, NULL, valbuf, 0);
+}
+
+void
+ppc_sysv_abi_broken_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, NULL, valbuf, 1);
+}
+
+void
+ppc_sysv_abi_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, valbuf, NULL, 0);
+}
+
+void
+ppc_sysv_abi_broken_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, valbuf, NULL, 1);
+}
+
/* 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)
+ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *type)
{
- if ((TYPE_LENGTH (value_type) == 16 || TYPE_LENGTH (value_type) == 8)
- && TYPE_VECTOR (value_type))
- return 0;
-
- return (TYPE_LENGTH (value_type) > 8);
+ return (do_ppc_sysv_return_value (type, NULL, NULL, NULL, 0)
+ == RETURN_VALUE_STRUCT_CONVENTION);
}
@@ -337,21 +577,6 @@
copy the buffer to the corresponding register return-value location
location; when OUTVAL is non-NULL, fill the buffer from the
corresponding register return-value location. */
-
-/* Potential ways that a function can return a value of a given type. */
-enum return_value_convention
-{
- /* Where the return value has been squeezed into one or more
- registers. */
- RETURN_VALUE_REGISTER_CONVENTION,
- /* Commonly known as the "struct return convention". The caller
- passes an additional hidden first parameter to the caller. That
- parameter contains the address at which the value being returned
- should be stored. While typically, and historically, used for
- large structs, this is convention is applied to values of many
- different types. */
- RETURN_VALUE_STRUCT_CONVENTION
-};
static enum return_value_convention
ppc64_sysv_abi_return_value (struct type *valtype, struct regcache *regcache,
Index: ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.19
diff -u -r1.19 ppc-tdep.h
--- ppc-tdep.h 3 Oct 2003 21:11:39 -0000 1.19
+++ ppc-tdep.h 4 Oct 2003 17:42:27 -0000
@@ -34,7 +34,18 @@
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 *);
+void ppc_sysv_abi_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf);
+void ppc_sysv_abi_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf);
+void ppc_sysv_abi_broken_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf);
+void ppc_sysv_abi_broken_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf);
CORE_ADDR ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
CORE_ADDR func_addr,
struct regcache *regcache,
Index: ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.8
diff -u -r1.8 ppcnbsd-tdep.c
--- ppcnbsd-tdep.c 17 Sep 2003 20:10:48 -0000 1.8
+++ ppcnbsd-tdep.c 4 Oct 2003 17:42:27 -0000
@@ -226,8 +226,11 @@
struct gdbarch *gdbarch)
{
set_gdbarch_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
-
+ /* For NetBSD, this is an on again, off again thing. Some systems
+ do use the broken struct convention, and some don't. */
set_gdbarch_use_struct_convention (gdbarch, ppcnbsd_use_struct_convention);
+ set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_broken_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_broken_store_return_value);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
}
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.166
diff -u -r1.166 rs6000-tdep.c
--- rs6000-tdep.c 3 Oct 2003 21:11:39 -0000 1.166
+++ rs6000-tdep.c 4 Oct 2003 17:42:28 -0000
@@ -1313,65 +1313,6 @@
return sp;
}
-/* Extract a function return value of type TYPE from raw register array
- REGBUF, and copy that return value into VALBUF in virtual format. */
-static void
-e500_extract_return_value (struct type *valtype, struct regcache *regbuf, void *valbuf)
-{
- int offset = 0;
- int vallen = TYPE_LENGTH (valtype);
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
- && vallen == 8
- && TYPE_VECTOR (valtype))
- {
- regcache_raw_read (regbuf, tdep->ppc_ev0_regnum + 3, valbuf);
- }
- else
- {
- /* Return value is copied starting from r3. Note that r3 for us
- is a pseudo register. */
- int offset = 0;
- int return_regnum = tdep->ppc_gp0_regnum + 3;
- int reg_size = DEPRECATED_REGISTER_RAW_SIZE (return_regnum);
- int reg_part_size;
- char *val_buffer;
- int copied = 0;
- int i = 0;
-
- /* Compute where we will start storing the value from. */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- {
- if (vallen <= reg_size)
- offset = reg_size - vallen;
- else
- offset = reg_size + (reg_size - vallen);
- }
-
- /* How big does the local buffer need to be? */
- if (vallen <= reg_size)
- val_buffer = alloca (reg_size);
- else
- val_buffer = alloca (vallen);
-
- /* Read all we need into our private buffer. We copy it in
- chunks that are as long as one register, never shorter, even
- if the value is smaller than the register. */
- while (copied < vallen)
- {
- reg_part_size = DEPRECATED_REGISTER_RAW_SIZE (return_regnum + i);
- /* It is a pseudo/cooked register. */
- regcache_cooked_read (regbuf, return_regnum + i,
- val_buffer + copied);
- copied += reg_part_size;
- i++;
- }
- /* Put the stuff in the return buffer. */
- memcpy (valbuf, val_buffer + offset, vallen);
- }
-}
-
/* PowerOpen always puts structures in memory. Vectors, which were
added later, do get returned in a register though. */
@@ -2046,30 +1987,6 @@
return regnum;
}
-/* Write into appropriate registers a function return value
- of type TYPE, given in virtual format. */
-static void
-e500_store_return_value (struct type *type, char *valbuf)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- /* Everything is returned in GPR3 and up. */
- int copied = 0;
- int i = 0;
- int len = TYPE_LENGTH (type);
- while (copied < len)
- {
- int regnum = gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3 + i;
- int reg_size = DEPRECATED_REGISTER_RAW_SIZE (regnum);
- char *reg_val_buf = alloca (reg_size);
-
- memcpy (reg_val_buf, valbuf + copied, reg_size);
- copied += reg_size;
- deprecated_write_register_gen (regnum, reg_val_buf);
- i++;
- }
-}
-
static void
rs6000_store_return_value (struct type *type, char *valbuf)
{
@@ -2835,6 +2752,11 @@
set_gdbarch_extract_return_value (gdbarch, ppc64_sysv_abi_extract_return_value);
set_gdbarch_store_return_value (gdbarch, ppc64_sysv_abi_store_return_value);
}
+ else if (sysv_abi && wordsize == 4)
+ {
+ set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_store_return_value);
+ }
else
{
set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
@@ -2873,8 +2795,6 @@
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
- set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value);
- set_gdbarch_deprecated_store_return_value (gdbarch, e500_store_return_value);
break;
default:
tdep->ppc_vr0_regnum = -1;
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-04 17:43 ` Andrew Cagney
@ 2003-10-06 19:12 ` Kevin Buettner
2003-10-10 20:22 ` Andrew Cagney
0 siblings, 1 reply; 11+ messages in thread
From: Kevin Buettner @ 2003-10-06 19:12 UTC (permalink / raw)
To: Andrew Cagney, Kevin Buettner; +Cc: gdb-patches, Jason R Thorpe
On Oct 4, 1:43pm, Andrew Cagney wrote:
> > Anyway, your patch looks okay to me. Feel free to check it in.
>
> Here is a revised version. It's now implemented using a wrapped
> ..._return_value.
>
> Still ok?
Please fix the following:
+ if (TYPE_LENGTH (type) <= 8)
+ {
+ if (outval)
+ {
+ /* This matches SVr4 PPC, it does not match gcc. */
+ /* The value is padded out to 8 bytes and then loaded, as
+ two "words" into r3/r3. */
The comment should say r3/r4, not r3/r3. Likewise here:
+ if (inval)
+ {
+ /* This matches SVr4 PPC, it does not match gcc. */
+ /* The value is padded out to 8 bytes and then loaded, as
+ two "words" into r3/r3. */
In a comment prior to do_ppc_sysv_return_value(), please specify
precisely which ABIs this function covers. The function name implies
that it's only SysV, but it looks to me like it's for SysV, Altivec,
and e500. I don't think it's worth making the function name more
verbose, but I do think it's important to list the other ABIs that
someone looking at this function needs to consider. Otherwise, a lot
of it doesn't make sense.
I'm puzzled by the following clause:
+ if (TYPE_LENGTH (type) == 8
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->ppc_ev0_regnum >= 0)
+ {
+ if (outval)
+ {
+ /* e500 places the return value in "ev2". */
+ regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 2, outval);
+ }
+ if (inval)
+ {
+ /* e500 places the return value in "ev2". */
+ regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 2, inval);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
I realize that this was lifted from code that existed elsewhere before,
but after comparing this to the e500 ABI doc that I have, this doesn't
look right. The ABI says:
Functions shall return values of 64-bit DSP types (__ev64_opaque__)
in r3.
IIRC, ev3 corresponds to the 64-bit r3, right? So, shouldn't the
above be returning the value in ev3 (rather than ev2)? Or am I
missing something?
This suggests that for each clause, it'd be useful to have a comment
listing which ABIs are (or are not) covered by that clause along with
additional descriptive text describing how the code corresponds to the
ABI for the non-obvious cases. E.g, for the above, I'd get rid of the
two ``e500 places the return value in "ev2".'' comments and instead place
something like this just above the ``if (outval)'' statement:
/* The e500 ABI places return values for the 64-bit DSP types
(__ev64_opaque__) in r3. However, in GDB-speak, ev3 corresponds
to the entire r3 value for e500, whereas r3 only corresponds
to the lower 32-bits. So place the 64-bit DSP type's value in
ev3. */
Hmm... I just realized that I don't have the Altivec ABI doc. Do
you have a pointer?
Thanks,
Kevin
P.S. For ppc_sysv_abi_use_struct_convention(), I was considering asking
you to organize it as follows:
int
ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *type)
{
int is_struct_return;
is_struct_return = (some concise logical expression);
/* Verify that the ``is_struct_return'' calculation matches
the value return implementation. */
assert (is_struct_return ==
(do_ppc_sysv_return_value (type, NULL, NULL, NULL, 0)
== RETURN_VALUE_STRUCT_CONVENTION));
return is_struct_return;
}
I decided against asking you to do this for the PPC SysV ABI because,
after again looking at the ABI, I concluded that more work is required
to verify the correctness of ``some concise logical expression'' wrt the
ABI than it was to do this verification by looking at
do_ppc_sysv_return_value(). I don't think I'd care to conclude that
this will always (or even usually) be the case after only considering
a few examples.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-06 19:12 ` Kevin Buettner
@ 2003-10-10 20:22 ` Andrew Cagney
2003-10-10 20:25 ` Jason Thorpe
2003-10-10 21:00 ` Kevin Buettner
0 siblings, 2 replies; 11+ messages in thread
From: Andrew Cagney @ 2003-10-10 20:22 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches, Jason R Thorpe
[-- Attachment #1: Type: text/plain, Size: 1440 bytes --]
> On Oct 4, 1:43pm, Andrew Cagney wrote:
> The comment should say r3/r4, not r3/r3. Likewise here:
Changed.
> + if (inval)
> + {
> + /* This matches SVr4 PPC, it does not match gcc. */
> + /* The value is padded out to 8 bytes and then loaded, as
> + two "words" into r3/r3. */
>
> In a comment prior to do_ppc_sysv_return_value(), please specify
> precisely which ABIs this function covers. The function name implies
> that it's only SysV, but it looks to me like it's for SysV, Altivec,
> and e500. I don't think it's worth making the function name more
> verbose, but I do think it's important to list the other ABIs that
> someone looking at this function needs to consider. Otherwise, a lot
> of it doesn't make sense.
Done, they call themselves "suplements".
> I realize that this was lifted from code that existed elsewhere before,
> but after comparing this to the e500 ABI doc that I have, this doesn't
> look right. The ABI says:
>
> Functions shall return values of 64-bit DSP types (__ev64_opaque__)
> in r3.
I suspect a cut/paste tipo.
> /* The e500 ABI places return values for the 64-bit DSP types
> (__ev64_opaque__) in r3. However, in GDB-speak, ev3 corresponds
> to the entire r3 value for e500, whereas r3 only corresponds
> to the lower 32-bits. So place the 64-bit DSP type's value in
> ev3. */
I've added a comment.
How is the attached?
Andrew
[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 17911 bytes --]
2003-10-10 Andrew Cagney <cagney@redhat.com>
* rs6000-tdep.c (e500_store_return_value): Delete function.
(e500_extract_return_value): Delete function.
(rs6000_gdbarch_init): When SYSV, set "extract_return_value" and
"restore_return_value" to "ppc_sysv_abi_extract_return_value" and
"ppc_sysv_abi_restore_return_value" where applicable.
* ppc-tdep.h: (ppc_sysv_abi_store_return_value): Declare.
(ppc_sysv_abi_extract_return_value): Declare.
(ppc_sysv_abi_broken_store_return_value): Declare.
(ppc_sysv_abi_broken_extract_return_value): Declare.
(ppc_sysv_abi_broken_use_struct_convention:) Delete declaration.
* ppc-sysv-tdep.c (return_value_convention): Move definition to
start of file.
(do_ppc_sysv_return_value): New function.
(ppc_sysv_abi_extract_return_value): New function.
(ppc_sysv_abi_store_return_value): New function.
(ppc_sysv_abi_broken_extract_return_value): New function.
(ppc_sysv_abi_broken_store_return_value): New function.
(ppc_sysv_abi_use_struct_convention): Call
do_ppc_sysv_return_value.
Index: ppc-sysv-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.15
diff -u -r1.15 ppc-sysv-tdep.c
--- ppc-sysv-tdep.c 10 Oct 2003 18:29:13 -0000 1.15
+++ ppc-sysv-tdep.c 10 Oct 2003 20:19:53 -0000
@@ -305,16 +305,264 @@
return sp;
}
+/* Potential ways that a function can return a value of a given type. */
+enum return_value_convention
+{
+ /* Where the return value has been squeezed into one or more
+ registers. */
+ RETURN_VALUE_REGISTER_CONVENTION,
+ /* Commonly known as the "struct return convention". The caller
+ passes an additional hidden first parameter to the caller. That
+ parameter contains the address at which the value being returned
+ should be stored. While typically, and historically, used for
+ large structs, this is convention is applied to values of many
+ different types. */
+ RETURN_VALUE_STRUCT_CONVENTION
+};
+
+/* Handle the return-value conventions specified by the SysV 32-bit
+ PowerPC ABI (including all the supplements):
+
+ no floating-point: floating-point values returned using 32-bit
+ general-purpose registers.
+
+ Altivec: 128-bit vectors returned using vector registers.
+
+ e500: 64-bit vectors returned using the full full 64 bit EV
+ register, floating-point values returned using 32-bit
+ general-purpose registers.
+
+ GCC (broken): Small struct values right (instead of left) aligned
+ when returned in general-purpose registers. */
+
+static enum return_value_convention
+do_ppc_sysv_return_value (struct type *type, struct regcache *regcache,
+ const void *inval, void *outval, int broken_gcc)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) <= 8
+ && ppc_floating_point_unit_p (current_gdbarch))
+ {
+ if (outval)
+ {
+ /* Floats and doubles stored in "f1". Convert the value to
+ the required type. */
+ char regval[MAX_REGISTER_SIZE];
+ struct type *regtype = register_type (current_gdbarch,
+ FP0_REGNUM + 1);
+ regcache_cooked_read (regcache, FP0_REGNUM + 1, regval);
+ convert_typed_floating (regval, regtype, outval, type);
+ }
+ if (inval)
+ {
+ /* Floats and doubles stored in "f1". Convert the value to
+ the register's "double" type. */
+ char regval[MAX_REGISTER_SIZE];
+ struct type *regtype = register_type (current_gdbarch, FP0_REGNUM);
+ convert_typed_floating (inval, type, regval, regtype);
+ regcache_cooked_write (regcache, FP0_REGNUM + 1, regval);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if ((TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4)
+ || (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 8 && tdep->wordsize == 4))
+ {
+ if (outval)
+ {
+ /* A long long, or a double stored in the 32 bit r3/r4. */
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ (bfd_byte *) outval + 0);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ (bfd_byte *) outval + 4);
+ }
+ if (inval)
+ {
+ /* A long long, or a double stored in the 32 bit r3/r4. */
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ (bfd_byte *) inval + 0);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ (bfd_byte *) inval + 4);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) <= tdep->wordsize)
+ {
+ if (outval)
+ {
+ /* Some sort of integer stored in r3. Since TYPE isn't
+ bigger than the register, sign extension isn't a problem
+ - just do everything unsigned. */
+ ULONGEST regval;
+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+ ®val);
+ store_unsigned_integer (outval, TYPE_LENGTH (type), regval);
+ }
+ if (inval)
+ {
+ /* Some sort of integer stored in r3. Use unpack_long since
+ that should handle any required sign extension. */
+ regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+ unpack_long (type, inval));
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
+ {
+ if (outval)
+ {
+ /* Altivec places the return value in "v2". */
+ regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, outval);
+ }
+ if (inval)
+ {
+ /* Altivec places the return value in "v2". */
+ regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, inval);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_LENGTH (type) == 8
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
+ {
+ /* The e500 ABI places return values for the 64-bit DSP types
+ (__ev64_opaque__) in r3. However, in GDB-speak, ev3
+ corresponds to the entire r3 value for e500, whereas GDB's r3
+ only corresponds to the least significant 32-bits. So place
+ the 64-bit DSP type's value in ev3. */
+ if (outval)
+ regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 3, outval);
+ if (inval)
+ regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 3, inval);
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (broken_gcc && TYPE_LENGTH (type) <= 8)
+ {
+ if (outval)
+ {
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each
+ register and then store that. */
+ /* Transfer any full words. */
+ int word = 0;
+ while (1)
+ {
+ ULONGEST reg;
+ int len = TYPE_LENGTH (type) - word * tdep->wordsize;
+ if (len <= 0)
+ break;
+ if (len > tdep->wordsize)
+ len = tdep->wordsize;
+ regcache_cooked_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + 3 + word,
+ ®);
+ store_unsigned_integer (((bfd_byte *) outval
+ + word * tdep->wordsize), len, reg);
+ word++;
+ }
+ }
+ if (inval)
+ {
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each
+ register and then store that. */
+ /* Transfer any full words. */
+ int word = 0;
+ while (1)
+ {
+ ULONGEST reg;
+ int len = TYPE_LENGTH (type) - word * tdep->wordsize;
+ if (len <= 0)
+ break;
+ if (len > tdep->wordsize)
+ len = tdep->wordsize;
+ reg = extract_unsigned_integer (((bfd_byte *) inval
+ + word * tdep->wordsize), len);
+ regcache_cooked_write_unsigned (regcache,
+ tdep->ppc_gp0_regnum + 3 + word,
+ reg);
+ word++;
+ }
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_LENGTH (type) <= 8)
+ {
+ if (outval)
+ {
+ /* This matches SVr4 PPC, it does not match GCC. */
+ /* The value is right-padded to 8 bytes and then loaded, as
+ two "words", into r3/r4. */
+ char regvals[MAX_REGISTER_SIZE * 2];
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (TYPE_LENGTH (type) > tdep->wordsize)
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ memcpy (outval, regvals, TYPE_LENGTH (type));
+ }
+ if (inval)
+ {
+ /* This matches SVr4 PPC, it does not match GCC. */
+ /* The value is padded out to 8 bytes and then loaded, as
+ two "words" into r3/r4. */
+ char regvals[MAX_REGISTER_SIZE * 2];
+ memset (regvals, 0, sizeof regvals);
+ memcpy (regvals, inval, TYPE_LENGTH (type));
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (TYPE_LENGTH (type) > tdep->wordsize)
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ return RETURN_VALUE_STRUCT_CONVENTION;
+}
+
+void
+ppc_sysv_abi_extract_return_value (struct type *type,
+ struct regcache *regcache, void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, NULL, valbuf, 0);
+}
+
+void
+ppc_sysv_abi_broken_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, NULL, valbuf, 1);
+}
+
+void
+ppc_sysv_abi_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, valbuf, NULL, 0);
+}
+
+void
+ppc_sysv_abi_broken_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf)
+{
+ do_ppc_sysv_return_value (type, regcache, valbuf, NULL, 1);
+}
+
/* 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_LENGTH (value_type) == 8)
- && TYPE_VECTOR (value_type))
- return 0;
-
- return (TYPE_LENGTH (value_type) > 8);
+ return (do_ppc_sysv_return_value (value_type, NULL, NULL, NULL, 0)
+ == RETURN_VALUE_STRUCT_CONVENTION);
}
/* Pass the arguments in either registers, or in the stack. Using the
@@ -617,22 +865,6 @@
copy the buffer to the corresponding register return-value location
location; when OUTVAL is non-NULL, fill the buffer from the
corresponding register return-value location. */
-
-/* Potential ways that a function can return a value of a given type. */
-enum return_value_convention
-{
- /* Where the return value has been squeezed into one or more
- registers. */
- RETURN_VALUE_REGISTER_CONVENTION,
- /* Commonly known as the "struct return convention". The caller
- passes an additional hidden first parameter to the caller. That
- parameter contains the address at which the value being returned
- should be stored. While typically, and historically, used for
- large structs, this is convention is applied to values of many
- different types. */
- RETURN_VALUE_STRUCT_CONVENTION
-};
-
static enum return_value_convention
ppc64_sysv_abi_return_value (struct type *valtype, struct regcache *regcache,
const void *inval, void *outval)
Index: ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.21
diff -u -r1.21 ppc-tdep.h
--- ppc-tdep.h 10 Oct 2003 18:29:13 -0000 1.21
+++ ppc-tdep.h 10 Oct 2003 20:19:53 -0000
@@ -35,7 +35,18 @@
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 *);
+void ppc_sysv_abi_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf);
+void ppc_sysv_abi_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf);
+void ppc_sysv_abi_broken_store_return_value (struct type *type,
+ struct regcache *regcache,
+ const void *valbuf);
+void ppc_sysv_abi_broken_extract_return_value (struct type *type,
+ struct regcache *regcache,
+ void *valbuf);
CORE_ADDR ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
CORE_ADDR func_addr,
struct regcache *regcache,
Index: ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.8
diff -u -r1.8 ppcnbsd-tdep.c
--- ppcnbsd-tdep.c 17 Sep 2003 20:10:48 -0000 1.8
+++ ppcnbsd-tdep.c 10 Oct 2003 20:19:53 -0000
@@ -226,8 +226,11 @@
struct gdbarch *gdbarch)
{
set_gdbarch_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
-
+ /* For NetBSD, this is an on again, off again thing. Some systems
+ do use the broken struct convention, and some don't. */
set_gdbarch_use_struct_convention (gdbarch, ppcnbsd_use_struct_convention);
+ set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_broken_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_broken_store_return_value);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
}
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.168
diff -u -r1.168 rs6000-tdep.c
--- rs6000-tdep.c 10 Oct 2003 18:29:13 -0000 1.168
+++ rs6000-tdep.c 10 Oct 2003 20:19:54 -0000
@@ -1313,65 +1313,6 @@
return sp;
}
-/* Extract a function return value of type TYPE from raw register array
- REGBUF, and copy that return value into VALBUF in virtual format. */
-static void
-e500_extract_return_value (struct type *valtype, struct regcache *regbuf, void *valbuf)
-{
- int offset = 0;
- int vallen = TYPE_LENGTH (valtype);
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
- && vallen == 8
- && TYPE_VECTOR (valtype))
- {
- regcache_raw_read (regbuf, tdep->ppc_ev0_regnum + 3, valbuf);
- }
- else
- {
- /* Return value is copied starting from r3. Note that r3 for us
- is a pseudo register. */
- int offset = 0;
- int return_regnum = tdep->ppc_gp0_regnum + 3;
- int reg_size = DEPRECATED_REGISTER_RAW_SIZE (return_regnum);
- int reg_part_size;
- char *val_buffer;
- int copied = 0;
- int i = 0;
-
- /* Compute where we will start storing the value from. */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
- {
- if (vallen <= reg_size)
- offset = reg_size - vallen;
- else
- offset = reg_size + (reg_size - vallen);
- }
-
- /* How big does the local buffer need to be? */
- if (vallen <= reg_size)
- val_buffer = alloca (reg_size);
- else
- val_buffer = alloca (vallen);
-
- /* Read all we need into our private buffer. We copy it in
- chunks that are as long as one register, never shorter, even
- if the value is smaller than the register. */
- while (copied < vallen)
- {
- reg_part_size = DEPRECATED_REGISTER_RAW_SIZE (return_regnum + i);
- /* It is a pseudo/cooked register. */
- regcache_cooked_read (regbuf, return_regnum + i,
- val_buffer + copied);
- copied += reg_part_size;
- i++;
- }
- /* Put the stuff in the return buffer. */
- memcpy (valbuf, val_buffer + offset, vallen);
- }
-}
-
/* PowerOpen always puts structures in memory. Vectors, which were
added later, do get returned in a register though. */
@@ -2046,30 +1987,6 @@
return regnum;
}
-/* Write into appropriate registers a function return value
- of type TYPE, given in virtual format. */
-static void
-e500_store_return_value (struct type *type, char *valbuf)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
- /* Everything is returned in GPR3 and up. */
- int copied = 0;
- int i = 0;
- int len = TYPE_LENGTH (type);
- while (copied < len)
- {
- int regnum = gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + 3 + i;
- int reg_size = DEPRECATED_REGISTER_RAW_SIZE (regnum);
- char *reg_val_buf = alloca (reg_size);
-
- memcpy (reg_val_buf, valbuf + copied, reg_size);
- copied += reg_size;
- deprecated_write_register_gen (regnum, reg_val_buf);
- i++;
- }
-}
-
static void
rs6000_store_return_value (struct type *type, char *valbuf)
{
@@ -2835,6 +2752,11 @@
set_gdbarch_extract_return_value (gdbarch, ppc64_sysv_abi_extract_return_value);
set_gdbarch_store_return_value (gdbarch, ppc64_sysv_abi_store_return_value);
}
+ else if (sysv_abi && wordsize == 4)
+ {
+ set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_store_return_value);
+ }
else
{
set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
@@ -2873,8 +2795,6 @@
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
- set_gdbarch_extract_return_value (gdbarch, e500_extract_return_value);
- set_gdbarch_deprecated_store_return_value (gdbarch, e500_store_return_value);
break;
default:
tdep->ppc_vr0_regnum = -1;
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-10 20:22 ` Andrew Cagney
@ 2003-10-10 20:25 ` Jason Thorpe
2003-10-10 20:32 ` Andrew Cagney
2003-10-10 21:00 ` Kevin Buettner
1 sibling, 1 reply; 11+ messages in thread
From: Jason Thorpe @ 2003-10-10 20:25 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, gdb-patches
On Friday, October 10, 2003, at 01:22 PM, Andrew Cagney wrote:
My apologies for not having a lot of time to keep up with this, but...
> + /* For NetBSD, this is an on again, off again thing. Some systems
> + do use the broken struct convention, and some don't. */
> set_gdbarch_use_struct_convention (gdbarch,
> ppcnbsd_use_struct_convention);
> + set_gdbarch_extract_return_value (gdbarch,
> ppc_sysv_abi_broken_extract_return_value);
> + set_gdbarch_store_return_value (gdbarch,
> ppc_sysv_abi_broken_store_return_value);
> set_solib_svr4_fetch_link_map_offsets (gdbarch,
>
> nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
on-again, off-again... which version of the compiler does which? Is
this a bug in GCC 2.95.3 (which is what shipped with NetBSD 1.6)?
(NetBSD 2.0 is going to ship with GCC 3.3.1.)
-- Jason R. Thorpe <thorpej@wasabisystems.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-10 20:25 ` Jason Thorpe
@ 2003-10-10 20:32 ` Andrew Cagney
2003-10-10 20:34 ` Jason Thorpe
0 siblings, 1 reply; 11+ messages in thread
From: Andrew Cagney @ 2003-10-10 20:32 UTC (permalink / raw)
To: Jason Thorpe; +Cc: Kevin Buettner, gdb-patches
>
> On Friday, October 10, 2003, at 01:22 PM, Andrew Cagney wrote:
>
> My apologies for not having a lot of time to keep up with this, but...
>
> + /* For NetBSD, this is an on again, off again thing. Some systems
> + do use the broken struct convention, and some don't. */
> set_gdbarch_use_struct_convention (gdbarch, ppcnbsd_use_struct_convention);
> + set_gdbarch_extract_return_value (gdbarch, ppc_sysv_abi_broken_extract_return_value);
> + set_gdbarch_store_return_value (gdbarch, ppc_sysv_abi_broken_store_return_value);
> set_solib_svr4_fetch_link_map_offsets (gdbarch,
> nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
>
> on-again, off-again... which version of the compiler does which? Is this a bug in GCC 2.95.3 (which is what shipped with NetBSD 1.6)? (NetBSD 2.0 is going to ship with GCC 3.3.1.)
The GCC shipped in 1.5 vs the one now in 1.6
$ gcc --version
2.95.3
Andrew
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-10 20:32 ` Andrew Cagney
@ 2003-10-10 20:34 ` Jason Thorpe
2003-10-10 21:01 ` Andrew Cagney
0 siblings, 1 reply; 11+ messages in thread
From: Jason Thorpe @ 2003-10-10 20:34 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Kevin Buettner, gdb-patches
On Friday, October 10, 2003, at 01:32 PM, Andrew Cagney wrote:
> The GCC shipped in 1.5 vs the one now in 1.6
> $ gcc --version
> 2.95.3
So, which one was right? The 1.5 compiler or the 1.6 compiler?
-- Jason R. Thorpe <thorpej@wasabisystems.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-10 20:22 ` Andrew Cagney
2003-10-10 20:25 ` Jason Thorpe
@ 2003-10-10 21:00 ` Kevin Buettner
2003-10-10 21:27 ` Andrew Cagney
1 sibling, 1 reply; 11+ messages in thread
From: Kevin Buettner @ 2003-10-10 21:00 UTC (permalink / raw)
To: Andrew Cagney, Kevin Buettner; +Cc: gdb-patches, Jason R Thorpe
On Oct 10, 4:22pm, Andrew Cagney wrote:
> How is the attached?
Very close. I just noticed the following:
+ if ((TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) == 8
+ && tdep->wordsize == 4)
+ || (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 8 && tdep->wordsize == 4))
According to do_ppc_sysv_return_value's comment, tdep->wordsize will
have to be 4. (Since it's for the "SysV 32-bit PowerPC ABI...")
So, could you please do the following:
- Remove the ``tdep->wordsize == 4'' tests in the above expression.
- Insert the following statement at some appropriate place
at the beginning of the function:
gdb_assert (tdep->wordsize == 4);
Once that's done, it's okay. (Go ahead and check it in.)
Thanks,
Kevin
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-10 20:34 ` Jason Thorpe
@ 2003-10-10 21:01 ` Andrew Cagney
0 siblings, 0 replies; 11+ messages in thread
From: Andrew Cagney @ 2003-10-10 21:01 UTC (permalink / raw)
To: Jason Thorpe; +Cc: Kevin Buettner, gdb-patches
> On Friday, October 10, 2003, at 01:32 PM, Andrew Cagney wrote:
>
> The GCC shipped in 1.5 vs the one now in 1.6
> $ gcc --version
> 2.95.3
>
> So, which one was right? The 1.5 compiler or the 1.6 compiler?
Neither, but from memory 1.5 was slightly closer:
> /* NetBSD is confused. It appears that 1.5 was using the correct SVr4
> convention but, 1.6 switched to the below broken convention. For
> the moment use the broken convention. Ulgh!. */
>
> static int
> ppcnbsd_use_struct_convention (int gcc_p, struct type *value_type)
> {
> if ((TYPE_LENGTH (value_type) == 16 || TYPE_LENGTH (value_type) == 8)
> && TYPE_VECTOR (value_type))
> return 0;
>
> return !(TYPE_LENGTH (value_type) == 1
> || TYPE_LENGTH (value_type) == 2
> || TYPE_LENGTH (value_type) == 4
> || TYPE_LENGTH (value_type) == 8);
> }
however, then GCC was getting:
+ /* GCC screwed up. The last register isn't "left" aligned.
+ Need to extract the least significant part of each
+ register and then store that. */
wrong.
Andrew
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [rfa?] Implement ppc32 SYSV {extract,store} return value
2003-10-10 21:00 ` Kevin Buettner
@ 2003-10-10 21:27 ` Andrew Cagney
0 siblings, 0 replies; 11+ messages in thread
From: Andrew Cagney @ 2003-10-10 21:27 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches, Jason R Thorpe
> On Oct 10, 4:22pm, Andrew Cagney wrote:
>
>
>> How is the attached?
>
>
> Very close. I just noticed the following:
>
> + if ((TYPE_CODE (type) == TYPE_CODE_INT
> + && TYPE_LENGTH (type) == 8
> + && tdep->wordsize == 4)
> + || (TYPE_CODE (type) == TYPE_CODE_FLT
> + && TYPE_LENGTH (type) == 8 && tdep->wordsize == 4))
>
> According to do_ppc_sysv_return_value's comment, tdep->wordsize will
> have to be 4. (Since it's for the "SysV 32-bit PowerPC ABI...")
>
> So, could you please do the following:
>
> - Remove the ``tdep->wordsize == 4'' tests in the above expression.
> - Insert the following statement at some appropriate place
> at the beginning of the function:
>
> gdb_assert (tdep->wordsize == 4);
>
> Once that's done, it's okay. (Go ahead and check it in.)
Committed (with tweaks),
Andrew
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2003-10-10 21:27 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-17 21:54 [rfa?] Implement ppc32 SYSV {extract,store} return value Andrew Cagney
2003-09-22 21:58 ` Kevin Buettner
2003-10-04 17:43 ` Andrew Cagney
2003-10-06 19:12 ` Kevin Buettner
2003-10-10 20:22 ` Andrew Cagney
2003-10-10 20:25 ` Jason Thorpe
2003-10-10 20:32 ` Andrew Cagney
2003-10-10 20:34 ` Jason Thorpe
2003-10-10 21:01 ` Andrew Cagney
2003-10-10 21:00 ` Kevin Buettner
2003-10-10 21:27 ` Andrew Cagney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox