mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-18 16:53:50 +08:00
* arm-tdep.c (convert_from_extended): New argument to hold the
type of floating point result we want to convert to. Make input argument const. Fix all callers. (convert_to_extended): Similarly. (arm_extract_return_value): Now takes a regcache argument. Change code to use regcache accessor functions. Correctly extract smaller-than-word results on big-endian machines. (arm_store_return_value): Now takes a regcache argument. Change code to use regcache accessor functions. Correctly zero/sign extend smaller than word results before storing into r0. (arm_gdbarch_init): Register new-style extract_return_value and store_return_value functions.
This commit is contained in:
@ -1,3 +1,18 @@
|
|||||||
|
2002-12-14 Richard Earnshaw <rearnsha@arm.com>
|
||||||
|
|
||||||
|
* arm-tdep.c (convert_from_extended): New argument to hold the
|
||||||
|
type of floating point result we want to convert to. Make input
|
||||||
|
argument const. Fix all callers.
|
||||||
|
(convert_to_extended): Similarly.
|
||||||
|
(arm_extract_return_value): Now takes a regcache argument. Change
|
||||||
|
code to use regcache accessor functions. Correctly extract
|
||||||
|
smaller-than-word results on big-endian machines.
|
||||||
|
(arm_store_return_value): Now takes a regcache argument. Change
|
||||||
|
code to use regcache accessor functions. Correctly zero/sign extend
|
||||||
|
smaller than word results before storing into r0.
|
||||||
|
(arm_gdbarch_init): Register new-style extract_return_value and
|
||||||
|
store_return_value functions.
|
||||||
|
|
||||||
2002-12-13 Michael Snyder <msnyder@to-limbo.toronto.redhat.com>
|
2002-12-13 Michael Snyder <msnyder@to-limbo.toronto.redhat.com>
|
||||||
|
|
||||||
* thread-db.c (thread_from_lwp): Uniquify error msg.
|
* thread-db.c (thread_from_lwp): Uniquify error msg.
|
||||||
|
153
gdb/arm-tdep.c
153
gdb/arm-tdep.c
@ -131,7 +131,10 @@ static void set_disassembly_flavor_sfunc(char *, int,
|
|||||||
struct cmd_list_element *);
|
struct cmd_list_element *);
|
||||||
static void set_disassembly_flavor (void);
|
static void set_disassembly_flavor (void);
|
||||||
|
|
||||||
static void convert_from_extended (void *ptr, void *dbl);
|
static void convert_from_extended (const struct floatformat *, const void *,
|
||||||
|
void *);
|
||||||
|
static void convert_to_extended (const struct floatformat *, void *,
|
||||||
|
const void *);
|
||||||
|
|
||||||
/* Define other aspects of the stack frame. We keep the offsets of
|
/* Define other aspects of the stack frame. We keep the offsets of
|
||||||
all saved registers, 'cause we need 'em a lot! We also keep the
|
all saved registers, 'cause we need 'em a lot! We also keep the
|
||||||
@ -1664,7 +1667,8 @@ arm_register_sim_regno (int regnum)
|
|||||||
little-endian systems. */
|
little-endian systems. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_from_extended (void *ptr, void *dbl)
|
convert_from_extended (const struct floatformat *fmt, const void *ptr,
|
||||||
|
void *dbl)
|
||||||
{
|
{
|
||||||
DOUBLEST d;
|
DOUBLEST d;
|
||||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||||
@ -1672,14 +1676,14 @@ convert_from_extended (void *ptr, void *dbl)
|
|||||||
else
|
else
|
||||||
floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
|
floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
|
||||||
ptr, &d);
|
ptr, &d);
|
||||||
floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
|
floatformat_from_doublest (fmt, &d, dbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
convert_to_extended (void *dbl, void *ptr)
|
convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr)
|
||||||
{
|
{
|
||||||
DOUBLEST d;
|
DOUBLEST d;
|
||||||
floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
|
floatformat_to_doublest (fmt, ptr, &d);
|
||||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||||
floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
|
floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
|
||||||
else
|
else
|
||||||
@ -2217,9 +2221,11 @@ arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
arm_extract_return_value (struct type *type,
|
arm_extract_return_value (struct type *type,
|
||||||
char regbuf[REGISTER_BYTES],
|
struct regcache *regs,
|
||||||
char *valbuf)
|
void *dst)
|
||||||
{
|
{
|
||||||
|
bfd_byte *valbuf = dst;
|
||||||
|
|
||||||
if (TYPE_CODE_FLT == TYPE_CODE (type))
|
if (TYPE_CODE_FLT == TYPE_CODE (type))
|
||||||
{
|
{
|
||||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
@ -2227,14 +2233,24 @@ arm_extract_return_value (struct type *type,
|
|||||||
switch (tdep->fp_model)
|
switch (tdep->fp_model)
|
||||||
{
|
{
|
||||||
case ARM_FLOAT_FPA:
|
case ARM_FLOAT_FPA:
|
||||||
convert_from_extended (®buf[REGISTER_BYTE (ARM_F0_REGNUM)],
|
{
|
||||||
|
/* The value is in register F0 in internal format. We need to
|
||||||
|
extract the raw value and then convert it to the desired
|
||||||
|
internal type. */
|
||||||
|
bfd_byte tmpbuf[FP_REGISTER_RAW_SIZE];
|
||||||
|
|
||||||
|
regcache_cooked_read (regs, ARM_F0_REGNUM, tmpbuf);
|
||||||
|
convert_from_extended (floatformat_from_type (type), tmpbuf,
|
||||||
valbuf);
|
valbuf);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARM_FLOAT_SOFT:
|
case ARM_FLOAT_SOFT:
|
||||||
case ARM_FLOAT_SOFT_VFP:
|
case ARM_FLOAT_SOFT_VFP:
|
||||||
memcpy (valbuf, ®buf[REGISTER_BYTE (ARM_A1_REGNUM)],
|
regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
|
||||||
TYPE_LENGTH (type));
|
if (TYPE_LENGTH (type) > 4)
|
||||||
|
regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
|
||||||
|
valbuf + INT_REGISTER_RAW_SIZE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -2244,9 +2260,50 @@ arm_extract_return_value (struct type *type,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (TYPE_CODE (type) == TYPE_CODE_INT
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_CHAR
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_BOOL
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_PTR
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_REF
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_ENUM)
|
||||||
|
{
|
||||||
|
/* If the the type is a plain integer, then the access is
|
||||||
|
straight-forward. Otherwise we have to play around a bit more. */
|
||||||
|
int len = TYPE_LENGTH (type);
|
||||||
|
int regno = ARM_A1_REGNUM;
|
||||||
|
ULONGEST tmp;
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
/* By using store_unsigned_integer we avoid having to do
|
||||||
|
anything special for small big-endian values. */
|
||||||
|
regcache_cooked_read_unsigned (regs, regno++, &tmp);
|
||||||
|
store_unsigned_integer (valbuf,
|
||||||
|
(len > INT_REGISTER_RAW_SIZE
|
||||||
|
? INT_REGISTER_RAW_SIZE : len),
|
||||||
|
tmp);
|
||||||
|
len -= INT_REGISTER_RAW_SIZE;
|
||||||
|
valbuf += INT_REGISTER_RAW_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memcpy (valbuf, ®buf[REGISTER_BYTE (ARM_A1_REGNUM)],
|
{
|
||||||
TYPE_LENGTH (type));
|
/* For a structure or union the behaviour is as if the value had
|
||||||
|
been stored to word-aligned memory and then loaded into
|
||||||
|
registers with 32-bit load instruction(s). */
|
||||||
|
int len = TYPE_LENGTH (type);
|
||||||
|
int regno = ARM_A1_REGNUM;
|
||||||
|
bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
regcache_cooked_read (regs, regno++, tmpbuf);
|
||||||
|
memcpy (valbuf, tmpbuf,
|
||||||
|
len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
|
||||||
|
len -= INT_REGISTER_RAW_SIZE;
|
||||||
|
valbuf += INT_REGISTER_RAW_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract from an array REGBUF containing the (raw) register state
|
/* Extract from an array REGBUF containing the (raw) register state
|
||||||
@ -2359,8 +2416,11 @@ arm_use_struct_convention (int gcc_p, struct type *type)
|
|||||||
TYPE, given in virtual format. */
|
TYPE, given in virtual format. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_store_return_value (struct type *type, char *valbuf)
|
arm_store_return_value (struct type *type, struct regcache *regs,
|
||||||
|
const void *src)
|
||||||
{
|
{
|
||||||
|
const bfd_byte *valbuf = src;
|
||||||
|
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||||
{
|
{
|
||||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||||
@ -2370,15 +2430,16 @@ arm_store_return_value (struct type *type, char *valbuf)
|
|||||||
{
|
{
|
||||||
case ARM_FLOAT_FPA:
|
case ARM_FLOAT_FPA:
|
||||||
|
|
||||||
convert_to_extended (valbuf, buf);
|
convert_to_extended (floatformat_from_type (type), buf, valbuf);
|
||||||
deprecated_write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
|
regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
|
||||||
FP_REGISTER_RAW_SIZE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARM_FLOAT_SOFT:
|
case ARM_FLOAT_SOFT:
|
||||||
case ARM_FLOAT_SOFT_VFP:
|
case ARM_FLOAT_SOFT_VFP:
|
||||||
deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
|
regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
|
||||||
TYPE_LENGTH (type));
|
if (TYPE_LENGTH (type) > 4)
|
||||||
|
regcache_cooked_write (regs, ARM_A1_REGNUM + 1,
|
||||||
|
valbuf + INT_REGISTER_RAW_SIZE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -2388,9 +2449,57 @@ arm_store_return_value (struct type *type, char *valbuf)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (TYPE_CODE (type) == TYPE_CODE_INT
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_CHAR
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_BOOL
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_PTR
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_REF
|
||||||
|
|| TYPE_CODE (type) == TYPE_CODE_ENUM)
|
||||||
|
{
|
||||||
|
if (TYPE_LENGTH (type) <= 4)
|
||||||
|
{
|
||||||
|
/* Values of one word or less are zero/sign-extended and
|
||||||
|
returned in r0. */
|
||||||
|
bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
|
||||||
|
LONGEST val = unpack_long (type, valbuf);
|
||||||
|
|
||||||
|
store_signed_integer (tmpbuf, INT_REGISTER_RAW_SIZE, val);
|
||||||
|
regcache_cooked_write (regs, ARM_A1_REGNUM, tmpbuf);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
|
{
|
||||||
TYPE_LENGTH (type));
|
/* Integral values greater than one word are stored in consecutive
|
||||||
|
registers starting with r0. This will always be a multiple of
|
||||||
|
the regiser size. */
|
||||||
|
int len = TYPE_LENGTH (type);
|
||||||
|
int regno = ARM_A1_REGNUM;
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
regcache_cooked_write (regs, regno++, valbuf);
|
||||||
|
len -= INT_REGISTER_RAW_SIZE;
|
||||||
|
valbuf += INT_REGISTER_RAW_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* For a structure or union the behaviour is as if the value had
|
||||||
|
been stored to word-aligned memory and then loaded into
|
||||||
|
registers with 32-bit load instruction(s). */
|
||||||
|
int len = TYPE_LENGTH (type);
|
||||||
|
int regno = ARM_A1_REGNUM;
|
||||||
|
bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
memcpy (tmpbuf, valbuf,
|
||||||
|
len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
|
||||||
|
regcache_cooked_write (regs, regno++, tmpbuf);
|
||||||
|
len -= INT_REGISTER_RAW_SIZE;
|
||||||
|
valbuf += INT_REGISTER_RAW_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the address of the place in which to copy the structure the
|
/* Store the address of the place in which to copy the structure the
|
||||||
@ -2869,8 +2978,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||||||
set_gdbarch_register_name (gdbarch, arm_register_name);
|
set_gdbarch_register_name (gdbarch, arm_register_name);
|
||||||
|
|
||||||
/* Returning results. */
|
/* Returning results. */
|
||||||
set_gdbarch_deprecated_extract_return_value (gdbarch, arm_extract_return_value);
|
set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
|
||||||
set_gdbarch_deprecated_store_return_value (gdbarch, arm_store_return_value);
|
set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
|
||||||
set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
|
set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
|
||||||
set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
|
set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
|
||||||
set_gdbarch_extract_struct_value_address (gdbarch,
|
set_gdbarch_extract_struct_value_address (gdbarch,
|
||||||
|
Reference in New Issue
Block a user