From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9014 invoked by alias); 21 Sep 2003 00:36:16 -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 9007 invoked from network); 21 Sep 2003 00:36:14 -0000 Received: from unknown (HELO localhost.redhat.com) (207.219.125.105) by sources.redhat.com with SMTP; 21 Sep 2003 00:36:14 -0000 Received: from redhat.com (localhost [127.0.0.1]) by localhost.redhat.com (Postfix) with ESMTP id 276C52B89 for ; Sat, 20 Sep 2003 20:36:13 -0400 (EDT) Message-ID: <3F6CF27D.9040500@redhat.com> Date: Sun, 21 Sep 2003 00:36:00 -0000 From: Andrew Cagney User-Agent: Mozilla/5.0 (X11; U; NetBSD macppc; en-US; rv:1.0.2) Gecko/20030820 X-Accept-Language: en-us, en MIME-Version: 1.0 To: gdb-patches@sources.redhat.com Subject: [rfa:ppc64] Fix return value Content-Type: multipart/mixed; boundary="------------010609020904010009060104" X-SW-Source: 2003-09/txt/msg00435.txt.bz2 This is a multi-part message in MIME format. --------------010609020904010009060104 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1891 Hello, The attached impements PPC64 SYSV specific versions of: use_struct_convention extract_return_value store_return_value It fixes: gdb.base/return2.exp: char value returned successfully gdb.base/return2.exp: int value returned successfully gdb.base/return2.exp: short value returned successfully gdb.base/structs.exp: p fun1 gdb.base/structs.exp: p fun2 gdb.base/structs.exp: p fun3 gdb.base/structs.exp: p fun4 gdb.base/structs.exp: p fun5 gdb.base/structs.exp: p fun6 gdb.base/structs.exp: p fun7 gdb.base/structs.exp: p fun8 gdb.c++/userdef.exp: print !one gdb.c++/userdef.exp: print -one gdb.c++/userdef.exp: print one != two gdb.c++/userdef.exp: print one % two gdb.c++/userdef.exp: print one & two gdb.c++/userdef.exp: print one && two gdb.c++/userdef.exp: print one * two gdb.c++/userdef.exp: print one + two gdb.c++/userdef.exp: print one - two gdb.c++/userdef.exp: print one / two gdb.c++/userdef.exp: print one < two gdb.c++/userdef.exp: print one << 31 gdb.c++/userdef.exp: print one <= two gdb.c++/userdef.exp: print one == two gdb.c++/userdef.exp: print one > two gdb.c++/userdef.exp: print one >= two gdb.c++/userdef.exp: print one >> 31 gdb.c++/userdef.exp: print one ^ two gdb.c++/userdef.exp: print one | two gdb.c++/userdef.exp: print one || two gdb.c++/userdef.exp: print ~one gdb.c++/userdef.exp: re-selected 'main' frame after inferior call Note the way I implemented it - the above wrap a generic ppc64_sysv_abi_return_value function and that handles all cases. I was finding that the more traditional technique (per my ppc post) was too error proned. Converting it to this style caused several mysterious regressions to mysteriously disappear. I'm thinking of proposing that this technique become the norm. Anyway, ok to commit? Andrew PS: I should note that PPC64's call function code is still on life support - it's not in a good shape at all. --------------010609020904010009060104 Content-Type: text/plain; name="diffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diffs" Content-length: 9098 2003-09-20 Andrew Cagney * rs6000-tdep.c (rs6000_gdbarch_init): When the 64 bit SysV ABI, set extract_return_value, store_return_value and use_struct_convention to ppc64_sysv_abi_extract_return_value, ppc64_sysv_abi_store_return_value and ppc64_sysv_abi_use_struct_convention. * ppc-tdep.h (ppc64_sysv_abi_extract_return_value): Declare. (ppc64_sysv_abi_store_return_value): Declare. (ppc64_sysv_abi_use_struct_convention): Declare. * ppc-sysv-tdep.c (ppc64_sysv_abi_extract_return_value): New function. (ppc64_sysv_abi_store_return_value): New function. (ppc64_sysv_abi_use_struct_convention): New function. (ppc64_sysv_abi_return_value): New function. Index: ppc-sysv-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v retrieving revision 1.12 diff -u -r1.12 ppc-sysv-tdep.c --- ppc-sysv-tdep.c 19 Sep 2003 16:22:39 -0000 1.12 +++ ppc-sysv-tdep.c 21 Sep 2003 00:06:28 -0000 @@ -325,3 +325,180 @@ return (TYPE_LENGTH (value_type) > 8); } + + +/* The 64 bit ABI retun value convention. + + Return non-zero if the return-value is stored in a register, return + 0 if the return-value is instead stored on the stack (a.k.a., + struct return convention). + + For a return-value stored in a register: when INVAL is non-NULL, + copy the buffer to the corresponding register return-value location + location; when OUTVAL is non-NULL, fill the buffer from the + corresponding register return-value location. */ + +static int +ppc64_sysv_abi_return_value (struct type *valtype, struct regcache *regcache, + const void *inval, void *outval) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + /* Floats and doubles in F1. */ + if (TYPE_CODE (valtype) == TYPE_CODE_FLT + && TYPE_LENGTH (valtype) <= 8) + { + char regval[MAX_REGISTER_SIZE]; + struct type *regtype = register_type (current_gdbarch, FP0_REGNUM); + if (inval != NULL) + { + convert_typed_floating (inval, valtype, regval, regtype); + regcache_cooked_write (regcache, FP0_REGNUM + 1, regval); + } + if (outval != NULL) + { + regcache_cooked_read (regcache, FP0_REGNUM + 1, regval); + convert_typed_floating (regval, regtype, outval, valtype); + } + return 1; + } + if (TYPE_CODE (valtype) == TYPE_CODE_INT + && TYPE_LENGTH (valtype) <= 8) + { + /* Integers in r3. */ + if (inval != NULL) + { + /* Be careful to sign extend the value. */ + regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3, + unpack_long (valtype, inval)); + } + if (outval != NULL) + { + /* Extract the integer from r3. Since this is truncating the + value, there isn't a sign extension problem. */ + ULONGEST regval; + regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3, + ®val); + store_unsigned_integer (outval, TYPE_LENGTH (valtype), regval); + } + return 1; + } + /* All pointers live in r3. */ + if (TYPE_CODE (valtype) == TYPE_CODE_PTR) + { + /* All pointers live in r3. */ + if (inval != NULL) + regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, inval); + if (outval != NULL) + regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, outval); + return 1; + } + if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY + && TYPE_LENGTH (valtype) <= 8 + && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT + && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) + { + /* Small character arrays are returned, right justified, in r3. */ + int offset = (register_size (current_gdbarch, tdep->ppc_gp0_regnum + 3) + - TYPE_LENGTH (valtype)); + if (inval != NULL) + regcache_cooked_write_part (regcache, tdep->ppc_gp0_regnum + 3, + offset, TYPE_LENGTH (valtype), inval); + if (outval != NULL) + regcache_cooked_read_part (regcache, tdep->ppc_gp0_regnum + 3, + offset, TYPE_LENGTH (valtype), outval); + return 1; + } + /* Big floating point values get stored in adjacent floating + point registers. */ + if (TYPE_CODE (valtype) == TYPE_CODE_FLT + && (TYPE_LENGTH (valtype) == 16 + || TYPE_LENGTH (valtype) == 32)) + { + if (inval || outval != NULL) + { + int i; + for (i = 0; i < TYPE_LENGTH (valtype) / 8; i++) + { + if (inval != NULL) + regcache_cooked_write (regcache, FP0_REGNUM + 1 + i, + (const bfd_byte *) inval + i * 8); + if (outval != NULL) + regcache_cooked_read (regcache, FP0_REGNUM + 1 + i, + (bfd_byte *) outval + i * 8); + } + } + return 1; + } + /* Complex values get returned in f1:f2, need to convert. */ + if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX + && (TYPE_LENGTH (valtype) == 8 || TYPE_LENGTH (valtype) == 16)) + { + if (regcache != NULL) + { + int i; + for (i = 0; i < 2; i++) + { + char regval[MAX_REGISTER_SIZE]; + struct type *regtype = register_type (current_gdbarch, FP0_REGNUM); + if (inval != NULL) + { + convert_typed_floating ((const bfd_byte *) inval + i * (TYPE_LENGTH (valtype) / 2), + valtype, regval, regtype); + regcache_cooked_write (regcache, FP0_REGNUM + 1 + i, regval); + } + if (outval != NULL) + { + regcache_cooked_read (regcache, FP0_REGNUM + 1 + i, regval); + convert_typed_floating (regval, regtype, + (bfd_byte *) outval + i * (TYPE_LENGTH (valtype) / 2), + valtype); + } + } + } + return 1; + } + /* Big complex values get stored in f1:f4. */ + if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX + && TYPE_LENGTH (valtype) == 32) + { + if (regcache != NULL) + { + int i; + for (i = 0; i < 4; i++) + { + if (inval != NULL) + regcache_cooked_write (regcache, FP0_REGNUM + 1 + i, + (const bfd_byte *) inval + i * 8); + if (outval != NULL) + regcache_cooked_read (regcache, FP0_REGNUM + 1 + i, + (bfd_byte *) outval + i * 8); + } + } + return 1; + } + return 0; +} + +int +ppc64_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type) +{ + return !ppc64_sysv_abi_return_value (value_type, NULL, NULL, NULL); +} + +void +ppc64_sysv_abi_extract_return_value (struct type *valtype, + struct regcache *regbuf, + void *valbuf) +{ + if (!ppc64_sysv_abi_return_value (valtype, regbuf, NULL, valbuf)) + error ("Function return value unknown"); +} + +void +ppc64_sysv_abi_store_return_value (struct type *valtype, + struct regcache *regbuf, + const void *valbuf) +{ + if (!ppc64_sysv_abi_return_value (valtype, regbuf, valbuf, NULL)) + error ("Function return value location unknown"); +} Index: ppc-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/ppc-tdep.h,v retrieving revision 1.18 diff -u -r1.18 ppc-tdep.h --- ppc-tdep.h 14 Sep 2003 02:04:44 -0000 1.18 +++ ppc-tdep.h 21 Sep 2003 00:06:28 -0000 @@ -47,6 +47,14 @@ void ppc_linux_supply_gregset (char *buf); void ppc_linux_supply_fpregset (char *buf); +int ppc64_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type); +void ppc64_sysv_abi_extract_return_value (struct type *valtype, + struct regcache *regbuf, + void *valbuf); +void ppc64_sysv_abi_store_return_value (struct type *valtype, + struct regcache *regbuf, + const void *valbuf); + /* From rs6000-tdep.c... */ CORE_ADDR rs6000_frame_saved_pc (struct frame_info *fi); Index: rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.161 diff -u -r1.161 rs6000-tdep.c --- rs6000-tdep.c 17 Sep 2003 14:24:30 -0000 1.161 +++ rs6000-tdep.c 21 Sep 2003 00:06:29 -0000 @@ -2830,9 +2830,16 @@ set_gdbarch_pc_regnum (gdbarch, 64); set_gdbarch_sp_regnum (gdbarch, 1); set_gdbarch_deprecated_fp_regnum (gdbarch, 1); - set_gdbarch_deprecated_extract_return_value (gdbarch, - rs6000_extract_return_value); - set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value); + if (sysv_abi && wordsize == 8) + { + set_gdbarch_extract_return_value (gdbarch, ppc64_sysv_abi_extract_return_value); + set_gdbarch_store_return_value (gdbarch, ppc64_sysv_abi_store_return_value); + } + else + { + set_gdbarch_deprecated_extract_return_value (gdbarch, rs6000_extract_return_value); + set_gdbarch_deprecated_store_return_value (gdbarch, rs6000_store_return_value); + } if (v->arch == bfd_arch_powerpc) switch (v->mach) @@ -2964,9 +2971,11 @@ /* Not sure on this. FIXMEmgo */ set_gdbarch_frame_args_skip (gdbarch, 8); - if (sysv_abi) + if (sysv_abi && wordsize == 4) set_gdbarch_use_struct_convention (gdbarch, ppc_sysv_abi_use_struct_convention); + else if (sysv_abi && wordsize == 8) + set_gdbarch_use_struct_convention (gdbarch, ppc64_sysv_abi_use_struct_convention); else set_gdbarch_use_struct_convention (gdbarch, rs6000_use_struct_convention); --------------010609020904010009060104--