* arm-tdep.c (arm_push_arguments): Rewrite using a two-pass loop.
authorAndrew Cagney <cagney@redhat.com>
Wed, 12 Jun 2002 21:46:05 +0000 (21:46 +0000)
committerAndrew Cagney <cagney@redhat.com>
Wed, 12 Jun 2002 21:46:05 +0000 (21:46 +0000)
(arm_debug): New static variable.
(_initialize_arm_tdep): Add ``set debug arm'' command.

gdb/ChangeLog
gdb/arm-tdep.c

index 19dd9356228811a76c4268a5d737395568791098..5a301d0e05727847665a41b0ba925dadd25719e0 100644 (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.
index f4b84fadf3a5540c90647ddc3d1d44fa72ac8510..33828fcbe500092ce99515ed2e019d00e7ceb543 100644 (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++)
-    {
-      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);
 }