mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-02 06:54:54 +00:00
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.
This commit is contained in:
parent
8d4ce20aa3
commit
e754ae69e1
@ -1,3 +1,25 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
2003-10-10 J. Brobecker <brobecker@gnat.com>
|
2003-10-10 J. Brobecker <brobecker@gnat.com>
|
||||||
|
|
||||||
* blockframe.c (inside_main_func): No longer use symbol_lookup()
|
* blockframe.c (inside_main_func): No longer use symbol_lookup()
|
||||||
|
@ -305,16 +305,262 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
|
|||||||
return sp;
|
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);
|
||||||
|
gdb_assert (tdep->wordsize == 4);
|
||||||
|
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)
|
||||||
|
|| (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
|
||||||
|
{
|
||||||
|
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
|
/* Structures 8 bytes or less long are returned in the r3 & r4
|
||||||
registers, according to the SYSV ABI. */
|
registers, according to the SYSV ABI. */
|
||||||
int
|
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 *value_type)
|
||||||
{
|
{
|
||||||
if ((TYPE_LENGTH (value_type) == 16 || TYPE_LENGTH (value_type) == 8)
|
return (do_ppc_sysv_return_value (value_type, NULL, NULL, NULL, 0)
|
||||||
&& TYPE_VECTOR (value_type))
|
== RETURN_VALUE_STRUCT_CONVENTION);
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (TYPE_LENGTH (value_type) > 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass the arguments in either registers, or in the stack. Using the
|
/* Pass the arguments in either registers, or in the stack. Using the
|
||||||
@ -617,22 +863,6 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
|
|||||||
copy the buffer to the corresponding register return-value location
|
copy the buffer to the corresponding register return-value location
|
||||||
location; when OUTVAL is non-NULL, fill the buffer from the
|
location; when OUTVAL is non-NULL, fill the buffer from the
|
||||||
corresponding register return-value location. */
|
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
|
static enum return_value_convention
|
||||||
ppc64_sysv_abi_return_value (struct type *valtype, struct regcache *regcache,
|
ppc64_sysv_abi_return_value (struct type *valtype, struct regcache *regcache,
|
||||||
const void *inval, void *outval)
|
const void *inval, void *outval)
|
||||||
|
@ -35,7 +35,18 @@ int ppc_linux_frameless_function_invocation (struct frame_info *);
|
|||||||
void ppc_linux_frame_init_saved_regs (struct frame_info *);
|
void ppc_linux_frame_init_saved_regs (struct frame_info *);
|
||||||
CORE_ADDR ppc_linux_frame_chain (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_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 ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
|
||||||
CORE_ADDR func_addr,
|
CORE_ADDR func_addr,
|
||||||
struct regcache *regcache,
|
struct regcache *regcache,
|
||||||
|
@ -226,8 +226,11 @@ ppcnbsd_init_abi (struct gdbarch_info info,
|
|||||||
struct gdbarch *gdbarch)
|
struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
set_gdbarch_pc_in_sigtramp (gdbarch, ppcnbsd_pc_in_sigtramp);
|
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_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,
|
set_solib_svr4_fetch_link_map_offsets (gdbarch,
|
||||||
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
|
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
|
||||||
}
|
}
|
||||||
|
@ -1313,65 +1313,6 @@ ran_out_of_registers_for_arguments:
|
|||||||
return sp;
|
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
|
/* PowerOpen always puts structures in memory. Vectors, which were
|
||||||
added later, do get returned in a register though. */
|
added later, do get returned in a register though. */
|
||||||
|
|
||||||
@ -2046,30 +1987,6 @@ rs6000_stab_reg_to_regnum (int num)
|
|||||||
return regnum;
|
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
|
static void
|
||||||
rs6000_store_return_value (struct type *type, char *valbuf)
|
rs6000_store_return_value (struct type *type, char *valbuf)
|
||||||
{
|
{
|
||||||
@ -2835,6 +2752,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
set_gdbarch_extract_return_value (gdbarch, ppc64_sysv_abi_extract_return_value);
|
set_gdbarch_extract_return_value (gdbarch, ppc64_sysv_abi_extract_return_value);
|
||||||
set_gdbarch_store_return_value (gdbarch, ppc64_sysv_abi_store_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
|
else
|
||||||
{
|
{
|
||||||
set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
|
set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value);
|
||||||
@ -2873,8 +2795,6 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, e500_dwarf2_reg_to_regnum);
|
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_read (gdbarch, e500_pseudo_register_read);
|
||||||
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
tdep->ppc_vr0_regnum = -1;
|
tdep->ppc_vr0_regnum = -1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user