* arm-tdep.c (arm_push_arguments): Rewrite using a two-pass loop.
(arm_debug): New static variable. (_initialize_arm_tdep): Add ``set debug arm'' command.
This commit is contained in:
parent
26216b9822
commit
6529d2ddb5
2 changed files with 118 additions and 83 deletions
|
@ -1,3 +1,9 @@
|
|||
2002-06-12 Andrew Cagney <ac131313@redhat.com>
|
||||
|
||||
* arm-tdep.c (arm_push_arguments): Rewrite using a two-pass loop.
|
||||
(arm_debug): New static variable.
|
||||
(_initialize_arm_tdep): Add ``set debug arm'' command.
|
||||
|
||||
2002-06-12 Andrew Cagney <ac131313@redhat.com>
|
||||
|
||||
* Makefile.in (sim_arm_h): Define.
|
||||
|
|
193
gdb/arm-tdep.c
193
gdb/arm-tdep.c
|
@ -44,6 +44,8 @@
|
|||
|
||||
#include "gdb_assert.h"
|
||||
|
||||
static int arm_debug;
|
||||
|
||||
/* Each OS has a different mechanism for accessing the various
|
||||
registers stored in the sigcontext structure.
|
||||
|
||||
|
@ -1410,104 +1412,125 @@ static CORE_ADDR
|
|||
arm_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
|
||||
int struct_return, CORE_ADDR struct_addr)
|
||||
{
|
||||
char *fp;
|
||||
int argnum, argreg, nstack_size;
|
||||
CORE_ADDR fp;
|
||||
int argnum;
|
||||
int argreg;
|
||||
int nstack;
|
||||
int simd_argreg;
|
||||
int second_pass;
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||
|
||||
/* Walk through the list of args and determine how large a temporary
|
||||
stack is required. Need to take care here as structs may be
|
||||
passed on the stack, and we have to to push them. */
|
||||
nstack_size = -4 * REGISTER_SIZE; /* Some arguments go into A1-A4. */
|
||||
if (struct_return) /* The struct address goes in A1. */
|
||||
nstack_size += REGISTER_SIZE;
|
||||
|
||||
/* Walk through the arguments and add their size to nstack_size. */
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
passed on the stack, and we have to to push them. On the second
|
||||
pass, do the store. */
|
||||
nstack = 0;
|
||||
fp = sp;
|
||||
for (second_pass = 0; second_pass < 2; second_pass++)
|
||||
{
|
||||
int len;
|
||||
struct type *arg_type;
|
||||
/* Compute the FP using the information computed during the
|
||||
first pass. */
|
||||
if (second_pass)
|
||||
fp = sp - nstack;
|
||||
|
||||
arg_type = check_typedef (VALUE_TYPE (args[argnum]));
|
||||
len = TYPE_LENGTH (arg_type);
|
||||
simd_argreg = 0;
|
||||
argreg = ARM_A1_REGNUM;
|
||||
nstack = 0;
|
||||
|
||||
nstack_size += len;
|
||||
}
|
||||
|
||||
/* Allocate room on the stack, and initialize our stack frame
|
||||
pointer. */
|
||||
fp = NULL;
|
||||
if (nstack_size > 0)
|
||||
{
|
||||
sp -= nstack_size;
|
||||
fp = (char *) sp;
|
||||
}
|
||||
|
||||
/* Initialize the integer argument register pointer. */
|
||||
argreg = ARM_A1_REGNUM;
|
||||
|
||||
/* The struct_return pointer occupies the first parameter passing
|
||||
register. */
|
||||
if (struct_return)
|
||||
write_register (argreg++, struct_addr);
|
||||
|
||||
/* Process arguments from left to right. Store as many as allowed
|
||||
in the parameter passing registers (A1-A4), and save the rest on
|
||||
the temporary stack. */
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
int len;
|
||||
char *val;
|
||||
CORE_ADDR regval;
|
||||
enum type_code typecode;
|
||||
struct type *arg_type, *target_type;
|
||||
|
||||
arg_type = check_typedef (VALUE_TYPE (args[argnum]));
|
||||
target_type = TYPE_TARGET_TYPE (arg_type);
|
||||
len = TYPE_LENGTH (arg_type);
|
||||
typecode = TYPE_CODE (arg_type);
|
||||
val = (char *) VALUE_CONTENTS (args[argnum]);
|
||||
|
||||
#if 1
|
||||
/* I don't know why this code was disable. The only logical use
|
||||
for a function pointer is to call that function, so setting
|
||||
the mode bit is perfectly fine. FN */
|
||||
/* If the argument is a pointer to a function, and it is a Thumb
|
||||
function, set the low bit of the pointer. */
|
||||
if (TYPE_CODE_PTR == typecode
|
||||
&& NULL != target_type
|
||||
&& TYPE_CODE_FUNC == TYPE_CODE (target_type))
|
||||
/* The struct_return pointer occupies the first parameter
|
||||
passing register. */
|
||||
if (struct_return)
|
||||
{
|
||||
CORE_ADDR regval = extract_address (val, len);
|
||||
if (arm_pc_is_thumb (regval))
|
||||
store_address (val, len, MAKE_THUMB_ADDR (regval));
|
||||
if (second_pass)
|
||||
{
|
||||
if (arm_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"struct return in %s = 0x%s\n",
|
||||
REGISTER_NAME (argreg),
|
||||
paddr (struct_addr));
|
||||
write_register (argreg, struct_addr);
|
||||
}
|
||||
argreg++;
|
||||
}
|
||||
#endif
|
||||
/* Copy the argument to general registers or the stack in
|
||||
register-sized pieces. Large arguments are split between
|
||||
registers and stack. */
|
||||
while (len > 0)
|
||||
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
|
||||
int len;
|
||||
struct type *arg_type;
|
||||
struct type *target_type;
|
||||
enum type_code typecode;
|
||||
char *val;
|
||||
|
||||
if (argreg <= ARM_LAST_ARG_REGNUM)
|
||||
arg_type = check_typedef (VALUE_TYPE (args[argnum]));
|
||||
len = TYPE_LENGTH (arg_type);
|
||||
target_type = TYPE_TARGET_TYPE (arg_type);
|
||||
typecode = TYPE_CODE (arg_type);
|
||||
val = VALUE_CONTENTS (args[argnum]);
|
||||
|
||||
/* If the argument is a pointer to a function, and it is a
|
||||
Thumb function, create a LOCAL copy of the value and set
|
||||
the THUMB bit in it. */
|
||||
if (second_pass
|
||||
&& TYPE_CODE_PTR == typecode
|
||||
&& target_type != NULL
|
||||
&& TYPE_CODE_FUNC == TYPE_CODE (target_type))
|
||||
{
|
||||
/* It's an argument being passed in a general register. */
|
||||
regval = extract_address (val, partial_len);
|
||||
write_register (argreg++, regval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push the arguments onto the stack. */
|
||||
write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE);
|
||||
fp += REGISTER_SIZE;
|
||||
CORE_ADDR regval = extract_address (val, len);
|
||||
if (arm_pc_is_thumb (regval))
|
||||
{
|
||||
val = alloca (len);
|
||||
store_address (val, len, MAKE_THUMB_ADDR (regval));
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the argument to general registers or the stack in
|
||||
register-sized pieces. Large arguments are split between
|
||||
registers and stack. */
|
||||
while (len > 0)
|
||||
{
|
||||
int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
|
||||
|
||||
if (argreg <= ARM_LAST_ARG_REGNUM)
|
||||
{
|
||||
/* The argument is being passed in a general purpose
|
||||
register. */
|
||||
if (second_pass)
|
||||
{
|
||||
CORE_ADDR regval = extract_address (val,
|
||||
partial_len);
|
||||
if (arm_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"arg %d in %s = 0x%s\n",
|
||||
argnum,
|
||||
REGISTER_NAME (argreg),
|
||||
phex (regval, REGISTER_SIZE));
|
||||
write_register (argreg, regval);
|
||||
}
|
||||
argreg++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (second_pass)
|
||||
{
|
||||
/* Push the arguments onto the stack. */
|
||||
if (arm_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"arg %d @ 0x%s + %d\n",
|
||||
argnum, paddr (fp), nstack);
|
||||
write_memory (fp + nstack, val, REGISTER_SIZE);
|
||||
}
|
||||
nstack += REGISTER_SIZE;
|
||||
}
|
||||
|
||||
len -= partial_len;
|
||||
val += partial_len;
|
||||
}
|
||||
|
||||
len -= partial_len;
|
||||
val += partial_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return adjusted stack pointer. */
|
||||
return sp;
|
||||
/* Return the botom of the argument list (pointed to by fp). */
|
||||
return fp;
|
||||
}
|
||||
|
||||
/* Pop the current frame. So long as the frame info has been
|
||||
|
@ -3104,4 +3127,10 @@ The valid values are:\n");
|
|||
prologue_cache.saved_regs = NULL;
|
||||
prologue_cache.extra_info = (struct frame_extra_info *)
|
||||
xcalloc (1, sizeof (struct frame_extra_info));
|
||||
|
||||
/* Debugging flag. */
|
||||
add_show_from_set (add_set_cmd ("arm", class_maintenance, var_zinteger,
|
||||
&arm_debug, "Set arm debugging.\n\
|
||||
When non-zero, arm specific debugging is enabled.", &setdebuglist),
|
||||
&showdebuglist);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue