* 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:
Andrew Cagney 2002-06-12 21:46:05 +00:00
parent 26216b9822
commit 6529d2ddb5
2 changed files with 118 additions and 83 deletions

View File

@ -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.

View File

@ -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;
if (argreg <= ARM_LAST_ARG_REGNUM)
int len;
struct type *arg_type;
struct type *target_type;
enum type_code typecode;
char *val;
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);
}