PATCH ARM arm_push_arguemntes->arm_push_dummy_call

Richard Earnshaw rearnsha@arm.com
Sat Mar 29 17:24:00 GMT 2003


This patch implements the new arm_push_dummy_call function and thus 
removes the deprecated arm_push_arguments and arm_store_struct_return 
functions.

R.

2003-03-29  Richard Earnshaw  <rearnsha@arm.com>

	* arm-tdep.c (arm_push_arguments): Delete.
	(struct stack_item): New type.
	(push_stack_item, pop_stack_item, arm_push_dummy_call): New functions.
	(arm_store_struct_return): Delete.
	(arm_gdbarch_init): Register arm_push_dummy_call.  Don't register
	arm_push_arguments or arm_store_struct_return.



-------------- next part --------------
Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.117
diff -p -r1.117 arm-tdep.c
*** arm-tdep.c	26 Mar 2003 22:39:52 -0000	1.117
--- arm-tdep.c	29 Mar 2003 17:05:16 -0000
*************** arm_fix_call_dummy (char *dummy, CORE_AD
*** 1334,1470 ****
    write_register (4, fun);
  }
  
- /* Note: ScottB
- 
-    This function does not support passing parameters using the FPA
-    variant of the APCS.  It passes any floating point arguments in the
-    general registers and/or on the stack.  */
- 
- static CORE_ADDR
- arm_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
- 		    int struct_return, CORE_ADDR struct_addr)
- {
-   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.  On the second
-      pass, do the store.  */
-   nstack = 0;
-   fp = sp;
-   for (second_pass = 0; second_pass < 2; second_pass++)
-     {
-       /* 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)
- 	{
- 	  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++;
- 	}
- 
-       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))
- 	    {
- 	      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;
- 	    }
- 
- 	}
-     }
- 
-   /* Return the bottom of the argument list (pointed to by fp).  */
-   return fp;
- }
- 
  /* Pop the current frame.  So long as the frame info has been
     initialized properly (see arm_init_extra_frame_info), this code
     works for dummy frames as well as regular frames.  I.e, there's no
--- 1334,1339 ----
*************** arm_pop_frame (void)
*** 1499,1504 ****
--- 1368,1528 ----
    flush_cached_frames ();
  }
  
+ /* When arguments must be pushed onto the stack, they go on in reverse
+    order.  The code below implements a FILO (stack) to do this.  */
+ 
+ struct stack_item
+ {
+   int len;
+   struct stack_item *prev;
+   void *data;
+ };
+ 
+ static struct stack_item *
+ push_stack_item (struct stack_item *prev, void *contents, int len)
+ {
+   struct stack_item *si;
+   si = xmalloc (sizeof (struct stack_item));
+   si->data = malloc (len);
+   si->len = len;
+   si->prev = prev;
+   memcpy (si->data, contents, len);
+   return si;
+ }
+ 
+ static struct stack_item *
+ pop_stack_item (struct stack_item *si)
+ {
+   struct stack_item *dead = si;
+   si = si->prev;
+   xfree (dead->data);
+   xfree (dead);
+   return si;
+ }
+ 
+ /* We currently only support passing parameters in integer registers.  This
+    conforms with GCC's default model.  Several other variants exist and
+    we should probably support some of them based on the selected ABI.  */
+ 
+ static CORE_ADDR
+ arm_push_dummy_call (struct gdbarch *gdbarch, struct regcache *regcache,
+ 		     CORE_ADDR dummy_addr, int nargs, struct value **args,
+ 		     CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
+ {
+   int argnum;
+   int argreg;
+   int nstack;
+   struct stack_item *si = NULL;
+ 
+   /* Set the return address.  For the ARM, the return breakpoint is always
+      at DUMMY_ADDR.  */
+   /* XXX Fix for Thumb.  */
+   regcache_cooked_write_unsigned (regcache, ARM_LR_REGNUM, dummy_addr);
+ 
+   /* 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 = 0;
+ 
+   argreg = ARM_A1_REGNUM;
+   nstack = 0;
+ 
+   /* Some platforms require a double-word aligned stack.  Make sure sp
+      is correctly aligned before we start.  We always do this even if
+      it isn't really needed -- it can never hurt things.  */
+   sp &= ~(CORE_ADDR)(2 * REGISTER_SIZE - 1);
+ 
+   /* The struct_return pointer occupies the first parameter
+      passing register.  */
+   if (struct_return)
+     {
+       if (arm_debug)
+ 	fprintf_unfiltered (gdb_stdlog, "struct return in %s = 0x%s\n",
+ 			    REGISTER_NAME (argreg), paddr (struct_addr));
+       regcache_cooked_write_unsigned (regcache, argreg, struct_addr);
+       argreg++;
+     }
+ 
+   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 (TYPE_CODE_PTR == typecode
+ 	  && target_type != NULL
+ 	  && TYPE_CODE_FUNC == TYPE_CODE (target_type))
+ 	{
+ 	  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.  */
+ 	      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));
+ 	      regcache_cooked_write_unsigned (regcache, argreg, regval);
+ 	      argreg++;
+ 	    }
+ 	  else
+ 	    {
+ 	      /* Push the arguments onto the stack.  */
+ 	      if (arm_debug)
+ 		fprintf_unfiltered (gdb_stdlog, "arg %d @ sp + %d\n",
+ 				    argnum, nstack);
+ 	      si = push_stack_item (si, val, REGISTER_SIZE);
+ 	      nstack += REGISTER_SIZE;
+ 	    }
+ 	      
+ 	  len -= partial_len;
+ 	  val += partial_len;
+ 	}
+     }
+   /* If we have an odd number of words to push, then decrement the stack
+      by one word now, so first stack argument will be dword aligned.  */
+   if (nstack & 4)
+     sp -= 4;
+ 
+   while (si)
+     {
+       sp -= si->len;
+       write_memory (sp, si->data, si->len);
+       si = pop_stack_item (si);
+     }
+ 
+   /* Finally, update teh SP register.  */
+   regcache_cooked_write_unsigned (regcache, ARM_SP_REGNUM, sp);
+ 
+   return sp;
+ }
+ 
  static void
  print_fpu_flags (int flags)
  {
*************** arm_store_return_value (struct type *typ
*** 2456,2470 ****
      }
  }
  
- /* Store the address of the place in which to copy the structure the
-    subroutine will return.  This is called from call_function.  */
- 
- static void
- arm_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
- {
-   write_register (ARM_A1_REGNUM, addr);
- }
- 
  static int
  arm_get_longjmp_target (CORE_ADDR *pc)
  {
--- 2480,2485 ----
*************** arm_gdbarch_init (struct gdbarch_info in
*** 2929,2936 ****
  
    set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
    set_gdbarch_push_return_address (gdbarch, arm_push_return_address);
! 
!   set_gdbarch_deprecated_push_arguments (gdbarch, arm_push_arguments);
  
    /* Frame handling.  */
    set_gdbarch_deprecated_frame_chain_valid (gdbarch, arm_frame_chain_valid);
--- 2944,2950 ----
  
    set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
    set_gdbarch_push_return_address (gdbarch, arm_push_return_address);
!   set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call);
  
    /* Frame handling.  */
    set_gdbarch_deprecated_frame_chain_valid (gdbarch, arm_frame_chain_valid);
*************** arm_gdbarch_init (struct gdbarch_info in
*** 2994,3000 ****
    /* Returning results.  */
    set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
    set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
-   set_gdbarch_deprecated_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,
  					    arm_extract_struct_value_address);
--- 3008,3013 ----


More information about the Gdb-patches mailing list