From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12383 invoked by alias); 10 Oct 2003 18:42:08 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 12376 invoked from network); 10 Oct 2003 18:42:07 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sources.redhat.com with SMTP; 10 Oct 2003 18:42:07 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.11.6/8.11.6) with ESMTP id h9AIg7M31429 for ; Fri, 10 Oct 2003 14:42:07 -0400 Received: from pobox.corp.redhat.com (pobox.corp.redhat.com [172.16.52.156]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id h9AIg6c16609 for ; Fri, 10 Oct 2003 14:42:06 -0400 Received: from localhost.redhat.com (devserv.devel.redhat.com [172.16.58.1]) by pobox.corp.redhat.com (8.12.8/8.12.8) with ESMTP id h9AIg695024729; Fri, 10 Oct 2003 14:42:06 -0400 Received: by localhost.redhat.com (Postfix, from userid 469) id B63112CCB6; Fri, 10 Oct 2003 14:53:18 -0400 (EDT) From: Elena Zannoni MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <16263.30.584298.427986@localhost.redhat.com> Date: Fri, 10 Oct 2003 18:42:00 -0000 To: vinschen@redhat.com, gdb-patches@sources.redhat.com Subject: Re: [RFA] sh-tdep.c: Fix float handling In-Reply-To: <20031004121102.GL11435@cygbert.vinschen.de> References: <20031004121102.GL11435@cygbert.vinschen.de> X-SW-Source: 2003-10/txt/msg00368.txt.bz2 Corinna Vinschen writes: > Hi, > > the below patch solves a problem which was unfortunately hidden by using > the sh-hms-sim.exp baseboard file. Removing the following line from > dejagnu/baseboards/sh-hms-sim.exp: > > set_board_info gdb,cannot_call_functions 1 > > uncovered that the current implementation doesn't get the ABI of floating > point CPUs (sh2e, sh3e, sh4) right. > Please add this expanation as a comment. I find cleared than your shorter comments. Just add it before the helper function. >From here.... > First, in contrast to non-FPU CPUs, arguments are never split between > registers and stack. If an argument doesn't fit in the remaining registers > it's always pushed entirely on the stack. My testing led me to the wrong > assumption that just types > 16 bytes are pushed entirely on the stack. > > Second, the FPU ABIs have a special way how to treat types as float types. > Structures with exactly one member, which is of type float or double, are > treated exactly as the base types float or double: > > struct sf { > float f; > }; > > struct sd { > double d; > }; > > are handled the same way as just > > float f; > > double d; > > As a result, arguments of these struct types are pushed into floating point > registers exactly as floats or doubles, using the same decision algorithm. > > The same is valid if these types are used as function return types. The > above structs are returned in fr0 resp. fr0,fr1 instead of in r0, r0,r1 > or even using struct convention as it is for other structs. > ....to here. > The below patch fixes this by adding a helper function sh_treat_as_flt(), Since this is a predicate, can you call it sh_treat_as_flt_p . > which evaluates if a type is treated as float type. The result of this > function is then used in sh_push_dummy_call_fpu(), > sh3e_sh4_extract_return_value() and sh3e_sh4_store_return_value() to > push resp. return these structs correctly. > > Over all, including the sh_use_struct_convention patch send 20 minutes ago > the FAIL count is lowered by 1 FAIL on non-FPU ABIs and 5 FAILs on FPU > ABIs, but that's only visible when tweaking sh-hms-sim.exp appropriately. > Ok otherwise. BTW, what multilibs are you testing? elena > > Corinna > > > * sh-tdep.c (sh_treat_as_flt): New function to recognize float > types correctly. > (sh_push_dummy_call_fpu): Fix argument passing rules. > (sh3e_sh4_extract_return_value): Call sh_treat_as_flt to recognize > float types. > (sh3e_sh4_store_return_value): Ditto. > > Index: sh-tdep.c > =================================================================== > RCS file: /cvs/src/src/gdb/sh-tdep.c,v > retrieving revision 1.145 > diff -u -p -r1.145 sh-tdep.c > --- sh-tdep.c 3 Oct 2003 08:13:37 -0000 1.145 > +++ sh-tdep.c 4 Oct 2003 11:32:00 -0000 > @@ -732,6 +749,33 @@ sh_next_flt_argreg (int len) > return FLOAT_ARG0_REGNUM + argreg; > } > > +/* Helper function which figures out, if a type is treated like a float type. > + The FPU based calling conventions (sh2e, sh3e, sh4, ...) are handling > + structs with exactly one member, which is of type float or double the same > + way as a simple float or double. That determines if such data is passed > + in float or general registers both, as argument or as return value. */ > +static int > +sh_treat_as_flt (struct type *type) > +{ > + int len = TYPE_LENGTH (type); > + > + /* Ordinary float types are obviously treated as float. */ > + if (TYPE_CODE (type) == TYPE_CODE_FLT) > + return 1; > + /* Otherwise non-struct types are not treated as float. */ > + if (TYPE_CODE (type) != TYPE_CODE_STRUCT) > + return 0; > + /* Otherwise structs with more than one memeber are not treated as float. */ > + if (TYPE_NFIELDS (type) != 1) > + return 0; > + /* Otherwise if the type of that member is float, the whole type is > + treated as float. */ > + if (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_FLT) > + return 1; > + /* Otherwise it's not treated as float. */ > + return 0; > +} > + > static CORE_ADDR > sh_push_dummy_call_fpu (struct gdbarch *gdbarch, > CORE_ADDR func_addr, > @@ -749,7 +793,8 @@ sh_push_dummy_call_fpu (struct gdbarch * > CORE_ADDR regval; > char *val; > int len, reg_size = 0; > - int pass_on_stack; > + int pass_on_stack = 0; > + int treat_as_flt; > > /* first force sp to a 4-byte alignment */ > sp = sh_frame_align (gdbarch, sp); > @@ -776,43 +821,41 @@ sh_push_dummy_call_fpu (struct gdbarch * > /* Some decisions have to be made how various types are handled. > This also differs in different ABIs. */ > pass_on_stack = 0; > - if (len > 16) > - pass_on_stack = 1; /* Types bigger than 16 bytes are passed on stack. */ > > /* Find out the next register to use for a floating point value. */ > - if (TYPE_CODE (type) == TYPE_CODE_FLT) > + treat_as_flt = sh_treat_as_flt (type); > + if (treat_as_flt) > flt_argreg = sh_next_flt_argreg (len); > + /* No data is passed partially in registers. */ > + else if (len > ((ARGLAST_REGNUM - argreg + 1) * 4)) > + pass_on_stack = 1; > > while (len > 0) > { > - if ((TYPE_CODE (type) == TYPE_CODE_FLT > - && flt_argreg > FLOAT_ARGLAST_REGNUM) > - || argreg > ARGLAST_REGNUM || pass_on_stack) > + if ((treat_as_flt && flt_argreg > FLOAT_ARGLAST_REGNUM) > + || (!treat_as_flt && (argreg > ARGLAST_REGNUM > + || pass_on_stack))) > { > - /* The remainder of the data goes entirely on the stack, > - 4-byte aligned. */ > + /* The data goes entirely on the stack, 4-byte aligned. */ > reg_size = (len + 3) & ~3; > write_memory (sp + stack_offset, val, reg_size); > stack_offset += reg_size; > } > - else if (TYPE_CODE (type) == TYPE_CODE_FLT > - && flt_argreg <= FLOAT_ARGLAST_REGNUM) > + else if (treat_as_flt && flt_argreg <= FLOAT_ARGLAST_REGNUM) > { > /* Argument goes in a float argument register. */ > reg_size = register_size (gdbarch, flt_argreg); > regval = extract_unsigned_integer (val, reg_size); > regcache_cooked_write_unsigned (regcache, flt_argreg++, regval); > } > - else if (argreg <= ARGLAST_REGNUM) > + else if (!treat_as_flt && argreg <= ARGLAST_REGNUM) > { > /* there's room in a register */ > reg_size = register_size (gdbarch, argreg); > regval = extract_unsigned_integer (val, reg_size); > regcache_cooked_write_unsigned (regcache, argreg++, regval); > } > - /* Store the value reg_size bytes at a time. This means that things > - larger than reg_size bytes may go partly in registers and partly > - on the stack. */ > + /* Store the value one register at a time or in one step on stack. */ > len -= reg_size; > val += reg_size; > } > @@ -930,7 +973,7 @@ static void > sh3e_sh4_extract_return_value (struct type *type, struct regcache *regcache, > void *valbuf) > { > - if (TYPE_CODE (type) == TYPE_CODE_FLT) > + if (sh_treat_as_flt (type)) > { > int len = TYPE_LENGTH (type); > int i, regnum = FP0_REGNUM; > @@ -971,7 +1014,7 @@ static void > sh3e_sh4_store_return_value (struct type *type, struct regcache *regcache, > const void *valbuf) > { > - if (TYPE_CODE (type) == TYPE_CODE_FLT) > + if (sh_treat_as_flt (type)) > { > int len = TYPE_LENGTH (type); > int i, regnum = FP0_REGNUM; > > > > -- > Corinna Vinschen > Cygwin Developer > Red Hat, Inc.