Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Jim Blandy <jimb@redhat.com>
To: gdb-patches@sources.redhat.com
Subject: [patch]: fix argument passing on S/390 and S/390x
Date: Tue, 01 Jul 2003 00:06:00 -0000	[thread overview]
Message-ID: <vt27k732jrd.fsf@zenia.home> (raw)


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


             reply	other threads:[~2003-07-01  0:06 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-01  0:06 Jim Blandy [this message]
2003-07-01  0:14 ` Jim Blandy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=vt27k732jrd.fsf@zenia.home \
    --to=jimb@redhat.com \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox