From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7259 invoked by alias); 27 Jun 2008 14:58:06 -0000 Received: (qmail 7241 invoked by uid 22791); 27 Jun 2008 14:58:02 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 27 Jun 2008 14:57:44 +0000 Received: (qmail 20490 invoked from network); 27 Jun 2008 14:57:42 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 27 Jun 2008 14:57:42 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.68) (envelope-from ) id 1KCFOP-0008CH-7B for gdb-patches@sourceware.org; Fri, 27 Jun 2008 14:57:41 +0000 Date: Fri, 27 Jun 2008 15:38:00 -0000 From: "Joseph S. Myers" To: gdb-patches@sourceware.org Subject: Re: Fix IA32 _Decimal128 argument-passing ABI In-Reply-To: Message-ID: References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-06/txt/msg00498.txt.bz2 This revised patch also handles structures or unions containing arrays containing _Decimal128 values (which also need 16-byte alignment as arguments). Test results same as for the previous version; OK to commit? 2008-06-27 Joseph Myers * i386-tdep.c (i386_16_byte_align_p): New. (i386_push_dummy_call): Determine stack space required for arguments going forwards allowing for 16-byte alignment, then push arguments going forwards. Index: i386-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/i386-tdep.c,v retrieving revision 1.259 diff -u -p -r1.259 i386-tdep.c --- i386-tdep.c 11 Jun 2008 22:03:49 -0000 1.259 +++ i386-tdep.c 27 Jun 2008 14:45:07 -0000 @@ -1521,6 +1521,34 @@ i386_get_longjmp_target (struct frame_in } +/* Check whether TYPE must be 16-byte-aligned when passed as a + function argument. 16-byte vectors, _Decimal128 and structures or + unions containing such types must be 16-byte-aligned; other + arguments are 4-byte-aligned. */ + +static int +i386_16_byte_align_p (struct type *type) +{ + type = check_typedef (type); + if ((TYPE_CODE (type) == TYPE_CODE_DECFLOAT + || (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))) + && TYPE_LENGTH (type) == 16) + return 1; + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + return i386_16_byte_align_p (TYPE_TARGET_TYPE (type)); + if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) + { + int i; + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + if (i386_16_byte_align_p (TYPE_FIELD_TYPE (type, i))) + return 1; + } + } + return 0; +} + static CORE_ADDR i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, @@ -1529,29 +1557,68 @@ i386_push_dummy_call (struct gdbarch *gd { gdb_byte buf[4]; int i; + int write_pass; + int args_space = 0; + + /* Determine the total space required for arguments and struct + return address in a first pass (allowing for 16-byte-aligned + arguments), then push arguments in a second pass. */ - /* Push arguments in reverse order. */ - for (i = nargs - 1; i >= 0; i--) + for (write_pass = 0; write_pass < 2; write_pass++) { - int len = TYPE_LENGTH (value_enclosing_type (args[i])); + int args_space_used = 0; + int have_16_byte_aligned_arg = 0; - /* The System V ABI says that: + if (struct_return) + { + if (write_pass) + { + /* Push value address. */ + store_unsigned_integer (buf, 4, struct_addr); + write_memory (sp, buf, 4); + args_space_used += 4; + } + else + args_space += 4; + } - "An argument's size is increased, if necessary, to make it a - multiple of [32-bit] words. This may require tail padding, - depending on the size of the argument." + for (i = 0; i < nargs; i++) + { + int len = TYPE_LENGTH (value_enclosing_type (args[i])); - This makes sure the stack stays word-aligned. */ - sp -= (len + 3) & ~3; - write_memory (sp, value_contents_all (args[i]), len); - } + if (write_pass) + { + if (i386_16_byte_align_p (value_enclosing_type (args[i]))) + args_space_used = align_up (args_space_used, 16); + + write_memory (sp + args_space_used, + value_contents_all (args[i]), len); + /* The System V ABI says that: + + "An argument's size is increased, if necessary, to make it a + multiple of [32-bit] words. This may require tail padding, + depending on the size of the argument." + + This makes sure the stack stays word-aligned. */ + args_space_used += align_up (len, 4); + } + else + { + if (i386_16_byte_align_p (value_enclosing_type (args[i]))) + { + args_space = align_up (args_space, 16); + have_16_byte_aligned_arg = 1; + } + args_space += align_up (len, 4); + } + } - /* Push value address. */ - if (struct_return) - { - sp -= 4; - store_unsigned_integer (buf, 4, struct_addr); - write_memory (sp, buf, 4); + if (!write_pass) + { + if (have_16_byte_aligned_arg) + args_space = align_up (args_space, 16); + sp -= args_space; + } } /* Store return address. */ -- Joseph S. Myers joseph@codesourcery.com