From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8606 invoked by alias); 26 Jun 2008 23:26:59 -0000 Received: (qmail 8596 invoked by uid 22791); 26 Jun 2008 23:26:58 -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; Thu, 26 Jun 2008 23:26:41 +0000 Received: (qmail 23970 invoked from network); 26 Jun 2008 23:26:39 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 26 Jun 2008 23:26:39 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.68) (envelope-from ) id 1KC0rO-0003sx-Et for gdb-patches@sourceware.org; Thu, 26 Jun 2008 23:26:38 +0000 Date: Fri, 27 Jun 2008 04:30:00 -0000 From: "Joseph S. Myers" To: gdb-patches@sourceware.org Subject: Fix IA32 _Decimal128 argument-passing ABI Message-ID: 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/msg00489.txt.bz2 The IA32 ABI for passing decimal floating-point arguments (and vector arguments) to functions was settled in GCC 4.3.1: _Decimal128 arguments and SSE vectors are 16-byte-aligned, as are structures and unions containing such types at any level, while other arguments (including _Decimal64) are 4-byte-aligned. This patch implements this ABI in GDB, so fixing the following test failures when testing with GCC 4.3 branch on i686-pc-linux-gnu: FAIL: gdb.base/dfp-test.exp: Backtrace function with correct _Decimal128 arguments. FAIL: gdb.base/dfp-test.exp: Correct _Decimal128 return value from called function. FAIL: gdb.base/dfp-test.exp: Call function with mixed decimal float arguments TEST. FAIL: gdb.base/dfp-test.exp: Call function with mixed decimal float arguments. FAIL: gdb.base/dfp-test.exp: Call function with many mixed decimal float arguments. OK to commit? 2008-06-26 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 26 Jun 2008 23:14:32 -0000 @@ -1521,6 +1521,32 @@ 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_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 +1555,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