* 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:
parent
7d695d0786
commit
b508a996e6
2 changed files with 147 additions and 23 deletions
|
@ -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>
|
||||
|
||||
* thread-db.c (thread_from_lwp): Uniquify error msg.
|
||||
|
|
155
gdb/arm-tdep.c
155
gdb/arm-tdep.c
|
@ -131,7 +131,10 @@ static void set_disassembly_flavor_sfunc(char *, int,
|
|||
struct cmd_list_element *);
|
||||
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
|
||||
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. */
|
||||
|
||||
static void
|
||||
convert_from_extended (void *ptr, void *dbl)
|
||||
convert_from_extended (const struct floatformat *fmt, const void *ptr,
|
||||
void *dbl)
|
||||
{
|
||||
DOUBLEST d;
|
||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||
|
@ -1672,14 +1676,14 @@ convert_from_extended (void *ptr, void *dbl)
|
|||
else
|
||||
floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
|
||||
ptr, &d);
|
||||
floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
|
||||
floatformat_from_doublest (fmt, &d, dbl);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_to_extended (void *dbl, void *ptr)
|
||||
convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr)
|
||||
{
|
||||
DOUBLEST d;
|
||||
floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
|
||||
floatformat_to_doublest (fmt, ptr, &d);
|
||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||
floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
|
||||
else
|
||||
|
@ -2217,9 +2221,11 @@ arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
|
|||
|
||||
static void
|
||||
arm_extract_return_value (struct type *type,
|
||||
char regbuf[REGISTER_BYTES],
|
||||
char *valbuf)
|
||||
struct regcache *regs,
|
||||
void *dst)
|
||||
{
|
||||
bfd_byte *valbuf = dst;
|
||||
|
||||
if (TYPE_CODE_FLT == TYPE_CODE (type))
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||
|
@ -2227,14 +2233,24 @@ arm_extract_return_value (struct type *type,
|
|||
switch (tdep->fp_model)
|
||||
{
|
||||
case ARM_FLOAT_FPA:
|
||||
convert_from_extended (®buf[REGISTER_BYTE (ARM_F0_REGNUM)],
|
||||
valbuf);
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
break;
|
||||
|
||||
case ARM_FLOAT_SOFT:
|
||||
case ARM_FLOAT_SOFT_VFP:
|
||||
memcpy (valbuf, ®buf[REGISTER_BYTE (ARM_A1_REGNUM)],
|
||||
TYPE_LENGTH (type));
|
||||
regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
|
||||
if (TYPE_LENGTH (type) > 4)
|
||||
regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
|
||||
valbuf + INT_REGISTER_RAW_SIZE);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2244,9 +2260,50 @@ arm_extract_return_value (struct type *type,
|
|||
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
|
||||
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
|
||||
|
@ -2359,8 +2416,11 @@ arm_use_struct_convention (int gcc_p, struct type *type)
|
|||
TYPE, given in virtual format. */
|
||||
|
||||
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)
|
||||
{
|
||||
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:
|
||||
|
||||
convert_to_extended (valbuf, buf);
|
||||
deprecated_write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
|
||||
FP_REGISTER_RAW_SIZE);
|
||||
convert_to_extended (floatformat_from_type (type), buf, valbuf);
|
||||
regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
|
||||
break;
|
||||
|
||||
case ARM_FLOAT_SOFT:
|
||||
case ARM_FLOAT_SOFT_VFP:
|
||||
deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
|
||||
TYPE_LENGTH (type));
|
||||
regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
|
||||
if (TYPE_LENGTH (type) > 4)
|
||||
regcache_cooked_write (regs, ARM_A1_REGNUM + 1,
|
||||
valbuf + INT_REGISTER_RAW_SIZE);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2388,9 +2449,57 @@ arm_store_return_value (struct type *type, char *valbuf)
|
|||
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
|
||||
{
|
||||
/* 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
|
||||
deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
@ -2869,8 +2978,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|||
set_gdbarch_register_name (gdbarch, arm_register_name);
|
||||
|
||||
/* Returning results. */
|
||||
set_gdbarch_deprecated_extract_return_value (gdbarch, arm_extract_return_value);
|
||||
set_gdbarch_deprecated_store_return_value (gdbarch, arm_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
|
||||
set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
|
||||
set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
|
||||
set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch,
|
||||
|
|
Loading…
Add table
Reference in a new issue