From patchwork Fri Jun 27 18:40:37 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Machado X-Patchwork-Id: 1804 Received: (qmail 6157 invoked by alias); 27 Jun 2014 18:40:46 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 6145 invoked by uid 89); 27 Jun 2014 18:40:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 27 Jun 2014 18:40:44 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1X0b4h-0000Xq-Sv from Luis_Gustavo@mentor.com ; Fri, 27 Jun 2014 11:40:39 -0700 Received: from SVR-ORW-FEM-06.mgc.mentorg.com ([147.34.97.120]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Fri, 27 Jun 2014 11:40:39 -0700 Received: from [172.30.72.175] (147.34.91.1) by SVR-ORW-FEM-06.mgc.mentorg.com (147.34.97.120) with Microsoft SMTP Server id 14.2.247.3; Fri, 27 Jun 2014 11:40:39 -0700 Message-ID: <53ADBAA5.9090404@codesourcery.com> Date: Fri, 27 Jun 2014 19:40:37 +0100 From: Luis Machado Reply-To: User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: Mark Kettenis CC: Subject: Re: [PATCH] Fix passing/returning of complex data for PowerPC 32-bit References: <53ABB5B3.1070803@codesourcery.com> <201406271030.s5RAUDJo025356@glazunov.sibelius.xs4all.nl> In-Reply-To: <201406271030.s5RAUDJo025356@glazunov.sibelius.xs4all.nl> X-IsSubscribed: yes On 06/27/2014 11:30 AM, Mark Kettenis wrote: >> Date: Thu, 26 Jun 2014 06:54:59 +0100 >> From: Luis Machado >> >> The PowerPC 32-bit unified ABI states that there are two ways of passing >> and returning complex type data: >> >> - Pointer, in a register, to a memory area. >> - Data in registers. >> >> The problem is that it is not clear how to detect which variation a >> program is using. GDB currently does a bit of both. It uses the first >> mechanism for passing parameters and uses both to return data, depending >> on the size of the data type. It is a bit messy because GDB is not >> handling complex types explicitly. >> >> Checking the gdb.base/callfuncs.exp testcase for a PowerPC 32-bit >> target, with code built with GCC, showed a few failures related to >> complex types. >> >> This patch steers GDB towards what GCC seems to generate for PowerPC >> 32-bit and handles complex type passing/return via general registers >> (the second option). All failures are gone. >> >> The problem here is if some other target/compiler is using the other >> variation. So, for those that have a PowerPC 32-bit handy, can you >> confirm it works reliably? I'm thinking AIX, Darwin or some other eabi >> target. > > AIX uses its own inplementations (rs6000_push_dummy_call and > rs6000_return_value). And we don't support Darwin on PowerPC. > True. That should be a non issue then. >> Otherwise, does this look reasonable? > > I agree that the "System V" support code should support the > ATR-PASS-COMPLEX-IN-GPRS ABI Attribute. This is what the Linux ABI > uses (it is included in ATR-LINUX) which pretty much is the direct > succssor of the System V ABI (which didn't specify anything about > complex floating-point support). > > If somebody really wants to support complex numbers on an embedded > system that uses ATR-PASS-COMPLEX-AS-STRUCT, they'll have to implement > an osabi sniffer for it and override the appropriate methods. > > Code generally looks good. Some nits below. The comments are a bit > elaborate though. I'd cut them down a bit; see my suggestion below. > > I adjusted the patch and compressed the comments according to the suggestions. Thanks! Luis 2014-06-27 Luis Machado * ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Explicitly handle passing of complex arguments. (do_ppc_sysv_return_value): Explicitly handle return of complex types. diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 1a880a6..7e18be5 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -269,6 +269,44 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, greg += 4; } } + else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + { + int type_size = TYPE_LENGTH (type); + int ngpr = type_size / tdep->wordsize; + + /* The PowerPC Unified 32-bit ABI specifies two mutually + conflicting conventions for passing and returning complex + floating-point values. These values are either treated as if + they were represented as a structure containing an array of + size two of the corresponding floating-point types (as + identified by the ATR-PASS-COMPLEX-AS-STRUCT ABI attribute) or + passed in the GPRs (as identified by the + ATR-PASS-COMPLEX-IN-GPRS ABI attribute). Since the latter + convention is the default in GCC, and mandated by the Linux + ABI, that's what we implement. */ + if (ngpr + greg > 11) + { + /* Pass parameter in the stack. */ + argoffset = align_up (argoffset, 8); + if (write_pass) + write_memory (sp + argoffset, val, len); + argoffset += len; + } + else + { + /* Pass the parameter in registers. */ + if (write_pass) + { + int i; + + for (i = 0; i < ngpr; i++) + regcache_cooked_write (regcache, + tdep->ppc_gp0_regnum + greg + i, + val + i * 4); + } + greg += ngpr; + } + } else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8 && !tdep->soft_float) { @@ -724,6 +762,30 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, } return RETURN_VALUE_REGISTER_CONVENTION; } + + /* The PowerPC Unified 32-bit specifies that complex + floating-point values are returned in the GPRs for + ATR-PASS-COMPLEX-IN-GPRS. */ + if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + { + int i, nregs; + int return_reg = tdep->ppc_gp0_regnum + 3; + + nregs = TYPE_LENGTH (type) / tdep->wordsize; + + for (i = 0; i < nregs; i++) + { + if (readbuf) + regcache_cooked_read (regcache, return_reg + i, + readbuf + i * tdep->wordsize); + if (writebuf) + regcache_cooked_write (regcache, return_reg + i, + writebuf + i * tdep->wordsize); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } + if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 16 && !tdep->soft_float