Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [patch]: fix argument passing on S/390 and S/390x
@ 2003-07-01  0:06 Jim Blandy
  2003-07-01  0:14 ` Jim Blandy
  0 siblings, 1 reply; 2+ messages in thread
From: Jim Blandy @ 2003-07-01  0:06 UTC (permalink / raw)
  To: gdb-patches


This is a patch that was discussed and approved long ago; only
recently has the legal paperwork finally come through.

2003-06-30  Jim Blandy  <jimb@redhat.com>

	Patch from IBM (authors unspecified, probably Ulrich Weigand and
	Gerhard Tonn) for argument passing on the S/390 and S/390x:
	* s390-tdep.c (S390_STACK_FRAME_OVERHEAD): This is always space
	for 16 registers, and then 32 more bytes.
	(S390_STACK_PARAMETER_ALIGNMENT, S390_NUM_FP_PARAMETER_REGISTERS):
	New macros.
	(is_double_arg): The s390x doesn't handle DOUBLE_ARGS specially.
	Move up in the file, since it's now used by is_simple_arg.
	(is_simple_arg): Don't assume registers are four bytes long.
	Exclude all double arguments.  Extended floats are not simple
	args.
	(is_power_of_two): New function.
	(pass_by_copy_ref): Call is_power_of_two, and check that the
	length fits in a register, rather than listing all the acceptable
	sizes.  Extended floats are not passed by reference.
	(s390_push_arguments): Don't assume registers are four bytes long.
	Reserve an argument register to point to the buffer for structures
	returned by value.  Use S390_NUM_FP_PARAMETER_REGISTERS and
	S390_STACK_FRAME_OVERHEAD.

Index: gdb/s390-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-tdep.c,v
retrieving revision 1.105
diff -c -r1.105 s390-tdep.c
*** gdb/s390-tdep.c	20 Jun 2003 13:57:28 -0000	1.105
--- gdb/s390-tdep.c	1 Jul 2003 00:04:28 -0000
***************
*** 93,99 ****
  #define S390X_SIGREGS_FP0_OFFSET      (216)
  #define S390_UC_MCONTEXT_OFFSET    (256)
  #define S390X_UC_MCONTEXT_OFFSET   (344)
! #define S390_STACK_FRAME_OVERHEAD  (GDB_TARGET_IS_ESAME ? 160:96)
  #define S390_SIGNAL_FRAMESIZE  (GDB_TARGET_IS_ESAME ? 160:96)
  #define s390_NR_sigreturn          119
  #define s390_NR_rt_sigreturn       173
--- 93,101 ----
  #define S390X_SIGREGS_FP0_OFFSET      (216)
  #define S390_UC_MCONTEXT_OFFSET    (256)
  #define S390X_UC_MCONTEXT_OFFSET   (344)
! #define S390_STACK_FRAME_OVERHEAD  16*DEPRECATED_REGISTER_SIZE+32
! #define S390_STACK_PARAMETER_ALIGNMENT  DEPRECATED_REGISTER_SIZE
! #define S390_NUM_FP_PARAMETER_REGISTERS (GDB_TARGET_IS_ESAME ? 4:2)
  #define S390_SIGNAL_FRAMESIZE  (GDB_TARGET_IS_ESAME ? 160:96)
  #define s390_NR_sigreturn          119
  #define s390_NR_rt_sigreturn       173
***************
*** 1331,1337 ****
     You'd think this would just be floats, doubles, long doubles, etc.
     But as an odd quirk, not mentioned in the ABI, GCC passes float and
     double singletons as if they were a plain float, double, etc.  (The
!    corresponding union types are handled normally.)  So we exclude
     those types here.  *shrug* */
  static int
  is_float_like (struct type *type)
--- 1333,1339 ----
     You'd think this would just be floats, doubles, long doubles, etc.
     But as an odd quirk, not mentioned in the ABI, GCC passes float and
     double singletons as if they were a plain float, double, etc.  (The
!    corresponding union types are handled normally.)  So we include
     those types here.  *shrug* */
  static int
  is_float_like (struct type *type)
***************
*** 1354,1359 ****
--- 1356,1380 ----
  }
  
  
+ /* Return non-zero if TYPE is a `DOUBLE_ARG', as defined by the
+    parameter passing conventions described in the "GNU/Linux for S/390
+    ELF Application Binary Interface Supplement".  Return zero
+    otherwise.  */
+ static int
+ is_double_arg (struct type *type)
+ {
+   unsigned length = TYPE_LENGTH (type);
+ 
+   /* The s390x ABI doesn't handle DOUBLE_ARGS specially.  */
+   if (GDB_TARGET_IS_ESAME)
+     return 0;
+ 
+   return ((is_integer_like (type)
+            || is_struct_like (type))
+           && length == 8);
+ }
+ 
+ 
  /* Return non-zero if TYPE is considered a `SIMPLE_ARG', as defined by
     the parameter passing conventions described in the "GNU/Linux for
     S/390 ELF Application Binary Interface Supplement".  Return zero
***************
*** 1365,1377 ****
  
    /* This is almost a direct translation of the ABI's language, except
       that we have to exclude 8-byte structs; those are DOUBLE_ARGs.  */
!   return ((is_integer_like (type) && length <= 4)
            || is_pointer_like (type)
!           || (is_struct_like (type) && length != 8)
!           || (is_float_like (type) && length == 16));
  }
  
  
  /* Return non-zero if TYPE should be passed as a pointer to a copy,
     zero otherwise.  TYPE must be a SIMPLE_ARG, as recognized by
     `is_simple_arg'.  */
--- 1386,1403 ----
  
    /* This is almost a direct translation of the ABI's language, except
       that we have to exclude 8-byte structs; those are DOUBLE_ARGs.  */
!   return ((is_integer_like (type) && length <= DEPRECATED_REGISTER_SIZE)
            || is_pointer_like (type)
!           || (is_struct_like (type) && !is_double_arg (type)));
  }
  
  
+ static int
+ is_power_of_two (unsigned int n)
+ {
+   return ((n & (n - 1)) == 0);
+ }
+ 
  /* Return non-zero if TYPE should be passed as a pointer to a copy,
     zero otherwise.  TYPE must be a SIMPLE_ARG, as recognized by
     `is_simple_arg'.  */
***************
*** 1380,1387 ****
  {
    unsigned length = TYPE_LENGTH (type);
  
!   return ((is_struct_like (type) && length != 1 && length != 2 && length != 4)
!           || (is_float_like (type) && length == 16));
  }
  
  
--- 1406,1413 ----
  {
    unsigned length = TYPE_LENGTH (type);
  
!   return (is_struct_like (type)
!           && !(is_power_of_two (length) && length <= DEPRECATED_REGISTER_SIZE));
  }
  
  
***************
*** 1404,1424 ****
  }
  
  
- /* Return non-zero if TYPE is a `DOUBLE_ARG', as defined by the
-    parameter passing conventions described in the "GNU/Linux for S/390
-    ELF Application Binary Interface Supplement".  Return zero
-    otherwise.  */
- static int
- is_double_arg (struct type *type)
- {
-   unsigned length = TYPE_LENGTH (type);
- 
-   return ((is_integer_like (type)
-            || is_struct_like (type))
-           && length == 8);
- }
- 
- 
  /* Round ADDR up to the next N-byte boundary.  N must be a power of
     two.  */
  static CORE_ADDR
--- 1430,1435 ----
***************
*** 1538,1546 ****
          
          sp = round_down (sp, alignment_of (type));
  
!         /* SIMPLE_ARG values get extended to 32 bits.  Assume every
!            argument is.  */
!         if (length < 4) length = 4;
          sp -= length;
        }
    }
--- 1549,1557 ----
          
          sp = round_down (sp, alignment_of (type));
  
!         /* SIMPLE_ARG values get extended to DEPRECATED_REGISTER_SIZE bytes. 
!            Assume every argument is.  */
!         if (length < DEPRECATED_REGISTER_SIZE) length = DEPRECATED_REGISTER_SIZE;
          sp -= length;
        }
    }
***************
*** 1561,1573 ****
      int gr = 2;
      CORE_ADDR starg = sp;
  
      for (i = 0; i < nargs; i++)
        {
          struct value *arg = args[i];
          struct type *type = VALUE_TYPE (arg);
          
          if (is_double_or_float (type)
!             && fr <= 2)
            {
              /* When we store a single-precision value in an FP register,
                 it occupies the leftmost bits.  */
--- 1572,1588 ----
      int gr = 2;
      CORE_ADDR starg = sp;
  
+     /* A struct is returned using general register 2 */
+     if (struct_return)
+       gr++;
+ 
      for (i = 0; i < nargs; i++)
        {
          struct value *arg = args[i];
          struct type *type = VALUE_TYPE (arg);
          
          if (is_double_or_float (type)
!             && fr <= S390_NUM_FP_PARAMETER_REGISTERS * 2 - 2)
            {
              /* When we store a single-precision value in an FP register,
                 it occupies the leftmost bits.  */
***************
*** 1594,1600 ****
              deprecated_write_register_gen (S390_GP0_REGNUM + gr,
  					   VALUE_CONTENTS (arg));
              deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1,
! 					   VALUE_CONTENTS (arg) + 4);
              gr += 2;
            }
          else
--- 1609,1615 ----
              deprecated_write_register_gen (S390_GP0_REGNUM + gr,
  					   VALUE_CONTENTS (arg));
              deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1,
! 					   VALUE_CONTENTS (arg) + DEPRECATED_REGISTER_SIZE);
              gr += 2;
            }
          else
***************
*** 1610,1618 ****
  
              if (is_simple_arg (type))
                {
!                 /* Simple args are always either extended to 32 bits,
!                    or pointers.  */
!                 starg = round_up (starg, 4);
  
                  /* Do we need to pass a pointer to our copy of this
                     argument?  */
--- 1625,1633 ----
  
              if (is_simple_arg (type))
                {
!                 /* Simple args are always extended to 
!                    DEPRECATED_REGISTER_SIZE bytes.  */
!                 starg = round_up (starg, DEPRECATED_REGISTER_SIZE);
  
                  /* Do we need to pass a pointer to our copy of this
                     argument?  */
***************
*** 1620,1637 ****
                    write_memory_signed_integer (starg, pointer_size,
                                                 copy_addr[i]);
                  else
!                   /* Simple args are always extended to 32 bits.  */
!                   write_memory_signed_integer (starg, 4,
                                                 extend_simple_arg (arg));
!                 starg += 4;
                }
              else
                {
                  /* You'd think we should say:
                     starg = round_up (starg, alignment_of (type));
                     Unfortunately, GCC seems to simply align the stack on
!                    a four-byte boundary, even when passing doubles.  */
!                 starg = round_up (starg, 4);
                  write_memory (starg, VALUE_CONTENTS (arg), length);
                  starg += length;
                }
--- 1635,1653 ----
                    write_memory_signed_integer (starg, pointer_size,
                                                 copy_addr[i]);
                  else
!                   /* Simple args are always extended to 
!                      DEPRECATED_REGISTER_SIZE bytes. */
!                   write_memory_signed_integer (starg, DEPRECATED_REGISTER_SIZE,
                                                 extend_simple_arg (arg));
!                 starg += DEPRECATED_REGISTER_SIZE;
                }
              else
                {
                  /* You'd think we should say:
                     starg = round_up (starg, alignment_of (type));
                     Unfortunately, GCC seems to simply align the stack on
!                    a four/eight-byte boundary, even when passing doubles. */
!                 starg = round_up (starg, S390_STACK_PARAMETER_ALIGNMENT);
                  write_memory (starg, VALUE_CONTENTS (arg), length);
                  starg += length;
                }
***************
*** 1642,1648 ****
    /* Allocate the standard frame areas: the register save area, the
       word reserved for the compiler (which seems kind of meaningless),
       and the back chain pointer.  */
!   sp -= 96;
  
    /* Write the back chain pointer into the first word of the stack
       frame.  This will help us get backtraces from within functions
--- 1658,1664 ----
    /* Allocate the standard frame areas: the register save area, the
       word reserved for the compiler (which seems kind of meaningless),
       and the back chain pointer.  */
!   sp -= S390_STACK_FRAME_OVERHEAD;
  
    /* Write the back chain pointer into the first word of the stack
       frame.  This will help us get backtraces from within functions


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [patch]: fix argument passing on S/390 and S/390x
  2003-07-01  0:06 [patch]: fix argument passing on S/390 and S/390x Jim Blandy
@ 2003-07-01  0:14 ` Jim Blandy
  0 siblings, 0 replies; 2+ messages in thread
From: Jim Blandy @ 2003-07-01  0:14 UTC (permalink / raw)
  To: gdb-patches


I've committed this to the 6.0 release branch, too.

Jim Blandy <jimb@redhat.com> writes:

> This is a patch that was discussed and approved long ago; only
> recently has the legal paperwork finally come through.
> 
> 2003-06-30  Jim Blandy  <jimb@redhat.com>
> 
> 	Patch from IBM (authors unspecified, probably Ulrich Weigand and
> 	Gerhard Tonn) for argument passing on the S/390 and S/390x:
> 	* s390-tdep.c (S390_STACK_FRAME_OVERHEAD): This is always space
> 	for 16 registers, and then 32 more bytes.
> 	(S390_STACK_PARAMETER_ALIGNMENT, S390_NUM_FP_PARAMETER_REGISTERS):
> 	New macros.
> 	(is_double_arg): The s390x doesn't handle DOUBLE_ARGS specially.
> 	Move up in the file, since it's now used by is_simple_arg.
> 	(is_simple_arg): Don't assume registers are four bytes long.
> 	Exclude all double arguments.  Extended floats are not simple
> 	args.
> 	(is_power_of_two): New function.
> 	(pass_by_copy_ref): Call is_power_of_two, and check that the
> 	length fits in a register, rather than listing all the acceptable
> 	sizes.  Extended floats are not passed by reference.
> 	(s390_push_arguments): Don't assume registers are four bytes long.
> 	Reserve an argument register to point to the buffer for structures
> 	returned by value.  Use S390_NUM_FP_PARAMETER_REGISTERS and
> 	S390_STACK_FRAME_OVERHEAD.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-07-01  0:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-01  0:06 [patch]: fix argument passing on S/390 and S/390x Jim Blandy
2003-07-01  0:14 ` Jim Blandy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox