From patchwork Tue Sep 5 18:21:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Weigand X-Patchwork-Id: 22641 Received: (qmail 57782 invoked by alias); 5 Sep 2017 18:21:39 -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 57717 invoked by uid 89); 5 Sep 2017 18:21:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 05 Sep 2017 18:21:32 +0000 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v85ILDco039464 for ; Tue, 5 Sep 2017 14:21:31 -0400 Received: from e06smtp12.uk.ibm.com (e06smtp12.uk.ibm.com [195.75.94.108]) by mx0a-001b2d01.pphosted.com with ESMTP id 2csx6d8xye-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 05 Sep 2017 14:21:31 -0400 Received: from localhost by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 5 Sep 2017 19:21:28 +0100 Received: from b06cxnps3074.portsmouth.uk.ibm.com (9.149.109.194) by e06smtp12.uk.ibm.com (192.168.101.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 5 Sep 2017 19:21:26 +0100 Received: from d06av22.portsmouth.uk.ibm.com (d06av22.portsmouth.uk.ibm.com [9.149.105.58]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v85ILPuX20840530 for ; Tue, 5 Sep 2017 18:21:25 GMT Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3F0AE4C044 for ; Tue, 5 Sep 2017 19:18:09 +0100 (BST) Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 203E24C04A for ; Tue, 5 Sep 2017 19:18:09 +0100 (BST) Received: from oc3748833570.ibm.com (unknown [9.164.150.234]) by d06av22.portsmouth.uk.ibm.com (Postfix) with ESMTP for ; Tue, 5 Sep 2017 19:18:09 +0100 (BST) Received: by oc3748833570.ibm.com (Postfix, from userid 1000) id 4D9AAD8086F; Tue, 5 Sep 2017 20:21:25 +0200 (CEST) Subject: [RFC][11/19] Target FP: Add conversion routines to target-float.{c, h} To: gdb-patches@sourceware.org Date: Tue, 5 Sep 2017 20:21:25 +0200 (CEST) From: "Ulrich Weigand" MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 17090518-0008-0000-0000-00000492CDCF X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17090518-0009-0000-0000-00001E23342F Message-Id: <20170905182125.4D9AAD8086F@oc3748833570.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-09-05_07:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1709050267 [RFC][11/19] Target FP: Add conversion routines to target-float.{c,h} This patch adds the following conversion routines: - target_float_to_longest - target_float_from_longest - target_float_from_ulongest - target_float_convert which call the equivalent decimal_ routines to handle decimal FP, and call helper routines that currently still go via DOUBLEST to handle binary FP. The target_float_convert routine not only handles BFP<->BFP and DFP<->DFP conversions, but also BFP<->DFP, which are implemented by converting to a string and back. These helpers are used in particular to implement conversion from and to FP in value_cast, without going through DOUBLEST there. In order to implement this for the FP<-integer case, the pack_long / pack_unsigned_long routines are extended to support floating-point values as output (thereby allowing use of value_from_[u]longest with a floating-point target type). This latter change also allows simplification of value_one. Bye, Ulrich ChangeLog: * target-float.c (floatformat_to_longest): New function. (floatformat_from_longest, floatformat_from_ulongest): Likewise. (floatformat_convert): Likewise. (target_float_to_longest): Likewise. (target_float_from_longest, target_float_from_ulongest): Likewise. (target_float_convert): Likewise. * target-float.h (target_float_to_longest): Add prototype. (target_float_from_longest, target_float_from_ulongest): Likewise. (target_float_convert): Likewise. * value.c (unpack_long): Use target_float_to_longest. (pack_long): Allow FP types. Use target_float_from_longest. (pack_unsigned_long): Likewise using target_float_from_ulongest. * valops.c: Include "target-float.h". Do not include "dfp.h". (value_cast): Handle conversions to FP using target_float_convert, value_from_ulongest, and value_from_longest. (value_one): Use value_from_longest for FP types as well. Index: binutils-gdb/gdb/target-float.c =================================================================== --- binutils-gdb.orig/gdb/target-float.c +++ binutils-gdb/gdb/target-float.c @@ -25,6 +25,64 @@ #include "target-float.h" +/* Helper routines operating on binary floating-point data. */ + +/* Convert the byte-stream ADDR, interpreted as floating-point format FMT, + to an integer value (rounding towards zero). */ +static LONGEST +floatformat_to_longest (const struct floatformat *fmt, const gdb_byte *addr) +{ + DOUBLEST d; + floatformat_to_doublest (fmt, addr, &d); + return (LONGEST) d; +} + +/* Convert signed integer VAL to a target floating-number of format FMT + and store it as byte-stream ADDR. */ +static void +floatformat_from_longest (const struct floatformat *fmt, gdb_byte *addr, + LONGEST val) +{ + DOUBLEST d = (DOUBLEST) val; + floatformat_from_doublest (fmt, &d, addr); +} + +/* Convert unsigned integer VAL to a target floating-number of format FMT + and store it as byte-stream ADDR. */ +static void +floatformat_from_ulongest (const struct floatformat *fmt, gdb_byte *addr, + ULONGEST val) +{ + DOUBLEST d = (DOUBLEST) val; + floatformat_from_doublest (fmt, &d, addr); +} + +/* Convert a floating-point number of format FROM_FMT from the target + byte-stream FROM to a floating-point number of format TO_FMT, and + store it to the target byte-stream TO. */ +static void +floatformat_convert (const gdb_byte *from, const struct floatformat *from_fmt, + gdb_byte *to, const struct floatformat *to_fmt) +{ + if (from_fmt == to_fmt) + { + /* The floating-point formats match, so we simply copy the data. */ + memcpy (to, from, floatformat_totalsize_bytes (to_fmt)); + } + else + { + /* The floating-point formats don't match. The best we can do + (apart from simulating the target FPU) is converting to the + widest floating-point type supported by the host, and then + again to the desired type. */ + DOUBLEST d; + + floatformat_to_doublest (from_fmt, from, &d); + floatformat_from_doublest (to_fmt, &d, to); + } +} + + /* Typed floating-point routines. These routines operate on floating-point values in target format, represented by a byte buffer interpreted as a "struct type", which may be either a binary or decimal floating-point @@ -97,3 +155,114 @@ target_float_from_string (gdb_byte *addr gdb_assert_not_reached ("unexpected type code"); } + +/* Convert the byte-stream ADDR, interpreted as floating-point type TYPE, + to an integer value (rounding towards zero). */ +LONGEST +target_float_to_longest (const gdb_byte *addr, const struct type *type) +{ + if (TYPE_CODE (type) == TYPE_CODE_FLT) + return floatformat_to_longest (floatformat_from_type (type), addr); + + if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + return decimal_to_longest (addr, TYPE_LENGTH (type), + gdbarch_byte_order (get_type_arch (type))); + + gdb_assert_not_reached ("unexpected type code"); +} + +/* Convert signed integer VAL to a target floating-number of type TYPE + and store it as byte-stream ADDR. */ +void +target_float_from_longest (gdb_byte *addr, const struct type *type, + LONGEST val) +{ + /* Ensure possible padding bytes in the target buffer are zeroed out. */ + memset (addr, 0, TYPE_LENGTH (type)); + + if (TYPE_CODE (type) == TYPE_CODE_FLT) + { + floatformat_from_longest (floatformat_from_type (type), addr, val); + return; + } + + if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + { + decimal_from_longest (val, addr, TYPE_LENGTH (type), + gdbarch_byte_order (get_type_arch (type))); + return; + } + + gdb_assert_not_reached ("unexpected type code"); +} + +/* Convert unsigned integer VAL to a target floating-number of type TYPE + and store it as byte-stream ADDR. */ +void +target_float_from_ulongest (gdb_byte *addr, const struct type *type, + ULONGEST val) +{ + /* Ensure possible padding bytes in the target buffer are zeroed out. */ + memset (addr, 0, TYPE_LENGTH (type)); + + if (TYPE_CODE (type) == TYPE_CODE_FLT) + { + floatformat_from_ulongest (floatformat_from_type (type), addr, val); + return; + } + + if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + { + decimal_from_ulongest (val, addr, TYPE_LENGTH (type), + gdbarch_byte_order (get_type_arch (type))); + return; + } + + gdb_assert_not_reached ("unexpected type code"); +} + +/* Convert a floating-point number of type FROM_TYPE from the target + byte-stream FROM to a floating-point number of type TO_TYPE, and + store it to the target byte-stream TO. */ +void +target_float_convert (const gdb_byte *from, const struct type *from_type, + gdb_byte *to, const struct type *to_type) +{ + /* Ensure possible padding bytes in the target buffer are zeroed out. */ + memset (to, 0, TYPE_LENGTH (to_type)); + + /* Use direct conversion routines if we have them. */ + + if (TYPE_CODE (from_type) == TYPE_CODE_FLT + && TYPE_CODE (to_type) == TYPE_CODE_FLT) + { + floatformat_convert (from, floatformat_from_type (from_type), + to, floatformat_from_type (to_type)); + return; + } + + if (TYPE_CODE (from_type) == TYPE_CODE_DECFLOAT + && TYPE_CODE (to_type) == TYPE_CODE_DECFLOAT) + { + decimal_convert (from, TYPE_LENGTH (from_type), + gdbarch_byte_order (get_type_arch (from_type)), + to, TYPE_LENGTH (to_type), + gdbarch_byte_order (get_type_arch (to_type))); + return; + } + + /* We cannot directly convert between binary and decimal floating-point + types, so go via an intermediary string. */ + + if ((TYPE_CODE (from_type) == TYPE_CODE_FLT + && TYPE_CODE (to_type) == TYPE_CODE_DECFLOAT) + || (TYPE_CODE (from_type) == TYPE_CODE_DECFLOAT + && TYPE_CODE (to_type) == TYPE_CODE_FLT)) + { + std::string str = target_float_to_string (from, from_type); + target_float_from_string (to, to_type, str); + return; + } + + gdb_assert_not_reached ("unexpected type code"); +} Index: binutils-gdb/gdb/target-float.h =================================================================== --- binutils-gdb.orig/gdb/target-float.h +++ binutils-gdb/gdb/target-float.h @@ -32,4 +32,16 @@ extern bool target_float_from_string (gd const struct type *type, std::string string); +extern LONGEST target_float_to_longest (const gdb_byte *addr, + const struct type *type); +extern void target_float_from_longest (gdb_byte *addr, + const struct type *type, + LONGEST val); +extern void target_float_from_ulongest (gdb_byte *addr, + const struct type *type, + ULONGEST val); +extern void target_float_convert (const gdb_byte *from, + const struct type *from_type, + gdb_byte *to, const struct type *to_type); + #endif Index: binutils-gdb/gdb/value.c =================================================================== --- binutils-gdb.orig/gdb/value.c +++ binutils-gdb/gdb/value.c @@ -2928,10 +2928,8 @@ unpack_long (struct type *type, const gd return extract_signed_integer (valaddr, len, byte_order); case TYPE_CODE_FLT: - return (LONGEST) extract_typed_floating (valaddr, type); - case TYPE_CODE_DECFLOAT: - return decimal_to_longest (valaddr, len, byte_order); + return target_float_to_longest (valaddr, type); case TYPE_CODE_PTR: case TYPE_CODE_REF: @@ -3545,6 +3543,11 @@ pack_long (gdb_byte *buf, struct type *t store_typed_address (buf, type, (CORE_ADDR) num); break; + case TYPE_CODE_FLT: + case TYPE_CODE_DECFLOAT: + target_float_from_longest (buf, type, num); + break; + default: error (_("Unexpected type (%d) encountered for integer constant."), TYPE_CODE (type)); @@ -3582,6 +3585,11 @@ pack_unsigned_long (gdb_byte *buf, struc store_typed_address (buf, type, (CORE_ADDR) num); break; + case TYPE_CODE_FLT: + case TYPE_CODE_DECFLOAT: + target_float_from_ulongest (buf, type, num); + break; + default: error (_("Unexpected type (%d) encountered " "for unsigned integer constant."), Index: binutils-gdb/gdb/valops.c =================================================================== --- binutils-gdb.orig/gdb/valops.c +++ binutils-gdb/gdb/valops.c @@ -34,7 +34,7 @@ #include "infcall.h" #include "dictionary.h" #include "cp-support.h" -#include "dfp.h" +#include "target-float.h" #include "tracepoint.h" #include "observer.h" #include "objfiles.h" @@ -464,29 +464,21 @@ value_cast (struct type *type, struct va return v; } - if (code1 == TYPE_CODE_FLT && scalar) - return value_from_double (to_type, value_as_double (arg2)); - else if (code1 == TYPE_CODE_DECFLOAT && scalar) - { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - int dec_len = TYPE_LENGTH (type); - gdb_byte dec[16]; - - if (code2 == TYPE_CODE_FLT) - decimal_from_doublest (value_as_double (arg2), - dec, dec_len, byte_order); - else if (code2 == TYPE_CODE_DECFLOAT) - decimal_convert (value_contents (arg2), TYPE_LENGTH (type2), - byte_order, dec, dec_len, byte_order); + if (is_floating_type (type) && scalar) + { + if (is_floating_value (arg2)) + { + struct value *v = allocate_value (to_type); + target_float_convert (value_contents (arg2), type2, + value_contents_raw (v), type); + return v; + } + /* The only option left is an integral type. */ - else if (TYPE_UNSIGNED (type2)) - decimal_from_ulongest (value_as_long (arg2), - dec, dec_len, byte_order); + if (TYPE_UNSIGNED (type2)) + return value_from_ulongest (to_type, value_as_long (arg2)); else - decimal_from_longest (value_as_long (arg2), - dec, dec_len, byte_order); - - return value_from_decfloat (to_type, dec); + return value_from_longest (to_type, value_as_long (arg2)); } else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM || code1 == TYPE_CODE_RANGE) @@ -870,19 +862,7 @@ value_one (struct type *type) struct type *type1 = check_typedef (type); struct value *val; - if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT) - { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - gdb_byte v[16]; - - decimal_from_string (v, TYPE_LENGTH (type), byte_order, "1"); - val = value_from_decfloat (type, v); - } - else if (TYPE_CODE (type1) == TYPE_CODE_FLT) - { - val = value_from_double (type, (DOUBLEST) 1); - } - else if (is_integral_type (type1)) + if (is_integral_type (type1) || is_floating_type (type1)) { val = value_from_longest (type, (LONGEST) 1); }