diff options
author | Andrew Cagney <cagney@redhat.com> | 2002-06-12 21:46:05 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2002-06-12 21:46:05 +0000 |
commit | 6529d2ddb5a9a1d724540d4f9f9278ad90993cb1 (patch) | |
tree | d918c8ef01d291abc5e4ab37144c7f6e3331b18e /gdb/arm-tdep.c | |
parent | 26216b98222fd93bf11128859575552d180d0576 (diff) | |
download | gdb-6529d2ddb5a9a1d724540d4f9f9278ad90993cb1.zip gdb-6529d2ddb5a9a1d724540d4f9f9278ad90993cb1.tar.gz gdb-6529d2ddb5a9a1d724540d4f9f9278ad90993cb1.tar.bz2 |
* 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.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r-- | gdb/arm-tdep.c | 195 |
1 files changed, 112 insertions, 83 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index f4b84fa..33828fc 100644 --- a/gdb/arm-tdep.c +++ b/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++) - { - int len; - struct type *arg_type; - - arg_type = check_typedef (VALUE_TYPE (args[argnum])); - len = TYPE_LENGTH (arg_type); - - 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++) + 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; - 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)) + /* Compute the FP using the information computed during the + first pass. */ + if (second_pass) + fp = sp - nstack; + + simd_argreg = 0; + argreg = ARM_A1_REGNUM; + nstack = 0; + + /* 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) - { - int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE; - if (argreg <= ARM_LAST_ARG_REGNUM) + for (argnum = 0; argnum < nargs; argnum++) + { + 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); + CORE_ADDR regval = extract_address (val, len); + if (arm_pc_is_thumb (regval)) + { + val = alloca (len); + store_address (val, len, MAKE_THUMB_ADDR (regval)); + } } - else + + /* Copy the argument to general registers or the stack in + register-sized pieces. Large arguments are split between + registers and stack. */ + while (len > 0) { - /* Push the arguments onto the stack. */ - write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE); - fp += REGISTER_SIZE; + 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); } |