From nobody Wed Feb 11 01:09:16 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1524148782294134.82575422087928; Thu, 19 Apr 2018 07:39:42 -0700 (PDT) Received: from localhost ([::1]:51782 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f9Ail-0000f9-V1 for importer@patchew.org; Thu, 19 Apr 2018 10:39:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52860) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f9ANb-0004qA-P3 for qemu-devel@nongnu.org; Thu, 19 Apr 2018 10:17:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f9ANV-0006AR-RJ for qemu-devel@nongnu.org; Thu, 19 Apr 2018 10:17:43 -0400 Received: from mail-wr0-x242.google.com ([2a00:1450:400c:c0c::242]:39272) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f9ANV-00069c-Gf for qemu-devel@nongnu.org; Thu, 19 Apr 2018 10:17:37 -0400 Received: by mail-wr0-x242.google.com with SMTP id q3-v6so4491709wrj.6 for ; Thu, 19 Apr 2018 07:17:37 -0700 (PDT) Received: from zen.linaro.local ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id 14sm5294543wmo.27.2018.04.19.07.17.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Apr 2018 07:17:30 -0700 (PDT) Received: from zen.linaroharston (localhost [127.0.0.1]) by zen.linaro.local (Postfix) with ESMTP id C52D83E0AC0; Thu, 19 Apr 2018 14:59:04 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=P3asiZvmEFcfZLk1LuNlofp3lbV5s5ec5DQZs8UIfRQ=; b=fIJLtgYdor5Q5yjQLQ5JLAxWy+U9M5HBxJcy0539lMWqRfWJez3nc82gk2vI7mqYwx dkaxNVq1uUAinkL/eTVDITfyVRuJo0O6qDIgCEOiMsDWXiQ44/kQGJihljKlmsPCx5ti 0m7RL2fQVcdQJ0pDVbd4T/ompuykl6wLyuUGc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=P3asiZvmEFcfZLk1LuNlofp3lbV5s5ec5DQZs8UIfRQ=; b=eh2tVct3sl7Qvgil8wTpJG1qVe3YGxGaepdbKizTHf09fThrXYObTQgOvloGeEO7Nf 9aEE8YPgoPMcGdxwIth+rBqY/+jgEcpd63SgmEk9xUGaAT5Gn1nkiV3rTvkKPi5WMbEh YJ2Kbp2DSbUcHMrkTRwBcdkYilfLg1QPuJlfdwyTau9oJXDamBJZrjzGPlj0+gbJXJ+i rVfw8D6N7ygm4VmsAaM54CxtWVAegPSFuuue2H584a39S17FsFjJ/M4Fxi+1+qtwlM34 9N6Oh4YUlRUsSZ6xkeC90VqmdDm1IwD1hP1F84hU3XqI1UTlGunsFGqRNMIFDoG7f5By RExw== X-Gm-Message-State: ALQs6tAXvizphg8zRPrSP5z+RLXieJV9tOVb5up/Ak4JNCYDf0KvibD2 i6ppkGocSwtlw8/hMWsXot7ugw== X-Google-Smtp-Source: AIpwx4+BnwZUNBDVVmwXGWV6jmAhz+SmWrV0pfQmc3SOdfNjCe7NxAC5DH8ZQa5vPiGoROnyy/ZNnw== X-Received: by 2002:adf:8e44:: with SMTP id n62-v6mr5205315wrb.159.1524147456271; Thu, 19 Apr 2018 07:17:36 -0700 (PDT) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: peter.maydell@linaro.org, cota@braap.org, famz@redhat.com, berrange@redhat.com, f4bug@amsat.org, richard.henderson@linaro.org, balrogg@gmail.com, aurelien@aurel32.net, agraf@suse.de Date: Thu, 19 Apr 2018 14:59:01 +0100 Message-Id: <20180419135901.30035-44-alex.bennee@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180419135901.30035-1-alex.bennee@linaro.org> References: <20180419135901.30035-1-alex.bennee@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c0c::242 Subject: [Qemu-devel] [PATCH v2 43/43] tests: fp-test add fcvt support (!INCOMPLETE WIP) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Alex=20Benn=C3=A9e?= , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 This adds support for the various FOO-to-BAR conversions to fp-test. It also defines PREC_HALF although currently that is not used and will need compile time detection for _Float16 support. I've added a small test file for testing against regressions. Signed-off-by: Alex Benn=C3=A9e --- tests/fp/fp-test.c | 535 +++++++++++++++++++++++--- tests/fp/qemu/regression-tests.fptest | 7 + 2 files changed, 479 insertions(+), 63 deletions(-) create mode 100644 tests/fp/qemu/regression-tests.fptest diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index 27db552160..320da2398a 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -38,15 +38,167 @@ struct input { }; =20 enum precision { + PREC_HALF, PREC_FLOAT, PREC_DOUBLE, PREC_QUAD, + /* Integers */ + PREC_INT16, + PREC_INT32, + PREC_INT64, + PREC_UINT16, + PREC_UINT32, + PREC_UINT64, + /* Float to Float conversions */ + PREC_HALF_TO_FLOAT, + PREC_HALF_TO_DOUBLE, + PREC_FLOAT_TO_HALF, PREC_FLOAT_TO_DOUBLE, + PREC_DOUBLE_TO_HALF, + PREC_DOUBLE_TO_FLOAT, + /* Float to Int conversions */ + PREC_HALF_TO_INT16, + PREC_HALF_TO_INT32, + PREC_HALF_TO_INT64, + PREC_FLOAT_TO_INT16, + PREC_FLOAT_TO_INT32, + PREC_FLOAT_TO_INT64, + PREC_DOUBLE_TO_INT16, + PREC_DOUBLE_TO_INT32, + PREC_DOUBLE_TO_INT64, + /* Float to unsigned int conversions */ + PREC_HALF_TO_UINT16, + PREC_HALF_TO_UINT32, + PREC_HALF_TO_UINT64, + PREC_FLOAT_TO_UINT16, + PREC_FLOAT_TO_UINT32, + PREC_FLOAT_TO_UINT64, + PREC_DOUBLE_TO_UINT16, + PREC_DOUBLE_TO_UINT32, + PREC_DOUBLE_TO_UINT64, + /* Int to float conversions */ + PREC_INT16_TO_HALF, + PREC_INT16_TO_FLOAT, + PREC_INT16_TO_DOUBLE, + PREC_INT32_TO_HALF, + PREC_INT32_TO_FLOAT, + PREC_INT32_TO_DOUBLE, + PREC_INT64_TO_HALF, + PREC_INT64_TO_FLOAT, + PREC_INT64_TO_DOUBLE, + /* Unsigned int to float conversions */ + PREC_UINT16_TO_HALF, + PREC_UINT16_TO_FLOAT, + PREC_UINT16_TO_DOUBLE, + PREC_UINT32_TO_HALF, + PREC_UINT32_TO_FLOAT, + PREC_UINT32_TO_DOUBLE, + PREC_UINT64_TO_HALF, + PREC_UINT64_TO_FLOAT, + PREC_UINT64_TO_DOUBLE, }; =20 +static enum precision get_input_prec(enum precision prec) +{ + /* Map conversions to input precision */ + if (prec >=3D PREC_HALF_TO_FLOAT) { + switch (prec) { + case PREC_HALF_TO_FLOAT: + case PREC_HALF_TO_DOUBLE: + case PREC_HALF_TO_INT16: + case PREC_HALF_TO_INT32: + case PREC_HALF_TO_INT64: + case PREC_HALF_TO_UINT16: + case PREC_HALF_TO_UINT32: + case PREC_HALF_TO_UINT64: + return PREC_HALF; + case PREC_FLOAT_TO_HALF: + case PREC_FLOAT_TO_DOUBLE: + case PREC_FLOAT_TO_INT16: + case PREC_FLOAT_TO_INT32: + case PREC_FLOAT_TO_INT64: + case PREC_FLOAT_TO_UINT16: + case PREC_FLOAT_TO_UINT32: + case PREC_FLOAT_TO_UINT64: + return PREC_FLOAT; + case PREC_DOUBLE_TO_HALF: + case PREC_DOUBLE_TO_FLOAT: + case PREC_DOUBLE_TO_INT16: + case PREC_DOUBLE_TO_INT32: + case PREC_DOUBLE_TO_INT64: + case PREC_DOUBLE_TO_UINT16: + case PREC_DOUBLE_TO_UINT32: + case PREC_DOUBLE_TO_UINT64: + return PREC_DOUBLE; + default: + assert(false); + } + } + + return prec; +} + +static enum precision get_output_prec(enum precision prec) +{ + /* Map conversions to input precision */ + if (prec >=3D PREC_HALF_TO_FLOAT) { + switch (prec) { + case PREC_FLOAT_TO_HALF: + case PREC_DOUBLE_TO_HALF: + case PREC_INT16_TO_HALF: + case PREC_INT32_TO_HALF: + case PREC_INT64_TO_HALF: + case PREC_UINT16_TO_HALF: + case PREC_UINT32_TO_HALF: + case PREC_UINT64_TO_HALF: + return PREC_HALF; + case PREC_HALF_TO_FLOAT: + case PREC_DOUBLE_TO_FLOAT: + return PREC_FLOAT; + case PREC_HALF_TO_DOUBLE: + case PREC_FLOAT_TO_DOUBLE: + return PREC_DOUBLE; + case PREC_HALF_TO_INT16: + case PREC_FLOAT_TO_INT16: + case PREC_DOUBLE_TO_INT16: + return PREC_INT16; + case PREC_HALF_TO_INT32: + case PREC_FLOAT_TO_INT32: + case PREC_DOUBLE_TO_INT32: + return PREC_INT32; + case PREC_HALF_TO_INT64: + case PREC_FLOAT_TO_INT64: + case PREC_DOUBLE_TO_INT64: + return PREC_INT64; + case PREC_HALF_TO_UINT16: + case PREC_FLOAT_TO_UINT16: + case PREC_DOUBLE_TO_UINT16: + return PREC_UINT16; + case PREC_HALF_TO_UINT32: + case PREC_FLOAT_TO_UINT32: + case PREC_DOUBLE_TO_UINT32: + return PREC_UINT32; + case PREC_HALF_TO_UINT64: + case PREC_FLOAT_TO_UINT64: + case PREC_DOUBLE_TO_UINT64: + return PREC_UINT64; + default: + assert(false); + } + } + + return prec; +} + +typedef struct { + char *opstr; + enum precision prec; +} map_to_prec; + struct op_desc { const char * const name; int n_operands; + map_to_prec *decode_tbl; }; =20 enum op { @@ -62,9 +214,46 @@ enum op { OP_ABS, OP_IS_NAN, OP_IS_INF, - OP_FLOAT_TO_DOUBLE, + /* All above are conversions */ + OP_FLOAT_TO_FLOAT, + OP_FLOAT_TO_INT, + OP_FLOAT_TO_UINT, + OP_INT_TO_FLOAT, + OP_UINT_TO_FLOAT }; =20 +map_to_prec float_to_float[] =3D { {"b16b32", PREC_HALF_TO_FLOAT}, + {"b16b64", PREC_HALF_TO_DOUBLE}, + {"b32b16", PREC_FLOAT_TO_HALF}, + {"b32b64", PREC_FLOAT_TO_DOUBLE}, + {"b64b16", PREC_DOUBLE_TO_HALF}, + {"b64b32", PREC_DOUBLE_TO_FLOAT}, + { NULL, 0} }; + +map_to_prec float_to_int[] =3D { {"b16b16", PREC_HALF_TO_INT16}, + {"b16b32", PREC_HALF_TO_INT16}, + {"b16b64", PREC_HALF_TO_INT16}, + {"b32b16", PREC_FLOAT_TO_INT16}, + {"b32b32", PREC_FLOAT_TO_INT32}, + {"b32b64", PREC_FLOAT_TO_INT64}, + {"b64b16", PREC_DOUBLE_TO_INT16}, + {"b64b32", PREC_DOUBLE_TO_INT32}, + {"b64b64", PREC_DOUBLE_TO_INT64}, + { NULL, 0} }; + +static enum precision decode_map_table(map_to_prec *tbl, char *opstr) +{ + while (tbl->opstr) { + if (strncmp(tbl->opstr, opstr, strlen(tbl->opstr)) =3D=3D 0) { + return tbl->prec; + } + tbl++; + } + + /* lookup failed */ + assert(false); +} + static const struct op_desc ops[] =3D { [OP_ADD] =3D { "+", 2 }, [OP_SUB] =3D { "-", 2 }, @@ -78,7 +267,11 @@ static const struct op_desc ops[] =3D { [OP_ABS] =3D { "A", 1 }, [OP_IS_NAN] =3D { "?N", 1 }, [OP_IS_INF] =3D { "?i", 1 }, - [OP_FLOAT_TO_DOUBLE] =3D { "cff", 1 }, + [OP_FLOAT_TO_FLOAT] =3D { "cff", 1, float_to_float }, + [OP_FLOAT_TO_INT] =3D { "cfi", 1, float_to_int }, + [OP_FLOAT_TO_UINT] =3D { "cfu", 1 }, + [OP_INT_TO_FLOAT] =3D { "cif", 1 }, + [OP_UINT_TO_FLOAT] =3D { "cuf", 1 }, }; =20 /* @@ -269,6 +462,159 @@ static enum error tester_check(const struct test_op *= t, uint64_t res64, return err; } =20 +static float get_float(struct operand op) +{ + switch (op.type) { + case OP_TYPE_QNAN: + return __builtin_nanf(""); + case OP_TYPE_SNAN: + return __builtin_nansf(""); + default: + return u64_to_float(op.val); + } +} + +static double get_double(struct operand op) +{ + switch (op.type) { + case OP_TYPE_QNAN: + return __builtin_nanf(""); + case OP_TYPE_SNAN: + return __builtin_nansf(""); + default: + return u64_to_double(op.val); + } +} + +static enum error host_tester_cff(struct test_op *t) +{ + float in32, res32; + double in64, res64; + bool result_is_nan; + uint8_t flags =3D 0; + + assert(t->op =3D=3D OP_FLOAT_TO_FLOAT); + + switch (t->prec) { + case PREC_HALF_TO_FLOAT: + case PREC_HALF_TO_DOUBLE: + return ERROR_NOT_HANDLED; + case PREC_FLOAT_TO_HALF: + return ERROR_NOT_HANDLED; + case PREC_FLOAT_TO_DOUBLE: + { + in32 =3D get_float(t->operands[0]); + t->expected_result.val =3D double_to_u64(get_double(t->expected_re= sult)); + res64 =3D (double) in32; + break; + } + case PREC_DOUBLE_TO_HALF: + return ERROR_NOT_HANDLED; + case PREC_DOUBLE_TO_FLOAT: + in64 =3D get_double(t->operands[0]); + t->expected_result.val =3D float_to_u64(get_float(t->expected_resu= lt)); + res32 =3D (float) in64; + break; + default: + return ERROR_NOT_HANDLED; + } + + flags =3D host_get_exceptions(); + + switch (t->prec) { + case PREC_HALF_TO_DOUBLE: + case PREC_FLOAT_TO_DOUBLE: + result_is_nan =3D isnan(res64); + return tester_check(t, res64, result_is_nan, flags); + case PREC_HALF_TO_FLOAT: + case PREC_DOUBLE_TO_FLOAT: + result_is_nan =3D isnan(res32); + return tester_check(t, res32, result_is_nan, flags); + default: + assert(false); + } + + return ERROR_NOT_HANDLED; +} + +static enum error host_tester_cfi(struct test_op *t) +{ + uint8_t flags =3D 0; + float in32; + double in64; + uint64_t res; + + assert(t->op =3D=3D OP_FLOAT_TO_INT || t->op =3D=3D OP_FLOAT_TO_UINT); + + switch (get_input_prec(t->prec)) { + case PREC_HALF: + return ERROR_NOT_HANDLED; + case PREC_FLOAT: + in32 =3D get_float(t->operands[0]); + break; + case PREC_DOUBLE: + in64 =3D get_double(t->operands[0]); + break; + default: + assert(false); + } + + + switch (t->prec) { + case PREC_HALF_TO_INT16: + case PREC_HALF_TO_INT32: + case PREC_HALF_TO_INT64: + return ERROR_NOT_HANDLED; + case PREC_FLOAT_TO_INT16: + { + int16_t oi16 =3D (int16_t) in32; + res =3D (uint64_t) oi16; + break; + } + case PREC_FLOAT_TO_INT32: + { + int32_t oi32 =3D (int32_t) in32; + res =3D (uint64_t) oi32; + break; + } + case PREC_FLOAT_TO_INT64: + { + int64_t oi64 =3D (int64_t) in32; + res =3D (uint64_t) oi64; + break; + } + case PREC_DOUBLE_TO_INT16: + { + int16_t oi16 =3D (int16_t) in64; + res =3D (uint64_t) oi16; + break; + } + case PREC_DOUBLE_TO_INT32: + { + int32_t oi32 =3D (int32_t) in64; + res =3D (uint64_t) oi32; + break; + } + case PREC_DOUBLE_TO_INT64: + { + int64_t oi64 =3D (int64_t) in64; + res =3D (uint64_t) oi64; + break; + } + default: + assert(false); + } + + flags =3D host_get_exceptions(); + + return tester_check(t, res, false, flags); +} + +static enum error host_tester_cif(struct test_op *t) +{ + return ERROR_NOT_HANDLED; +} + static enum error host_tester(struct test_op *t) { uint64_t res64; @@ -280,6 +626,20 @@ static enum error host_tester(struct test_op *t) host_set_exceptions(default_exceptions); } =20 + /* Handle conversions first */ + switch (t->op) { + case OP_FLOAT_TO_FLOAT: + return host_tester_cff(t); + case OP_FLOAT_TO_INT: + case OP_FLOAT_TO_UINT: + return host_tester_cfi(t); + case OP_INT_TO_FLOAT: + case OP_UINT_TO_FLOAT: + return host_tester_cif(t); + default: + break; + } + if (t->prec =3D=3D PREC_FLOAT) { float a, b, c; float *in[] =3D { &a, &b, &c }; @@ -396,40 +756,68 @@ static enum error host_tester(struct test_op *t) flags =3D host_get_exceptions(); res64 =3D double_to_u64(res); result_is_nan =3D isnan(res); - } else if (t->prec =3D=3D PREC_FLOAT_TO_DOUBLE) { - float a; - double res; - - if (t->operands[0].type =3D=3D OP_TYPE_QNAN) { - a =3D __builtin_nanf(""); - } else if (t->operands[0].type =3D=3D OP_TYPE_SNAN) { - a =3D __builtin_nansf(""); - } else { - a =3D u64_to_float(t->operands[0].val); - } - - if (t->expected_result.type =3D=3D OP_TYPE_QNAN) { - t->expected_result.val =3D double_to_u64(__builtin_nan("")); - } else if (t->expected_result.type =3D=3D OP_TYPE_SNAN) { - t->expected_result.val =3D double_to_u64(__builtin_nans("")); - } - - switch (t->op) { - case OP_FLOAT_TO_DOUBLE: - res =3D a; - break; - default: - return ERROR_NOT_HANDLED; - } - flags =3D host_get_exceptions(); - res64 =3D double_to_u64(res); - result_is_nan =3D isnan(res); } else { return ERROR_NOT_HANDLED; /* XXX */ } return tester_check(t, res64, result_is_nan, flags); } =20 +static enum error soft_tester_cff(struct test_op *t, float_status *s) +{ + float in32, res32; + double in64, res64; + bool result_is_nan; + + assert(t->op =3D=3D OP_FLOAT_TO_FLOAT); + + switch (t->prec) { + case PREC_HALF_TO_FLOAT: + case PREC_HALF_TO_DOUBLE: + return ERROR_NOT_HANDLED; + case PREC_FLOAT_TO_HALF: + return ERROR_NOT_HANDLED; + case PREC_FLOAT_TO_DOUBLE: + { + in32 =3D get_float(t->operands[0]); + t->expected_result.val =3D double_to_u64(get_double(t->expected_re= sult)); + res64 =3D float32_to_float64(in32, s); + break; + } + case PREC_DOUBLE_TO_HALF: + return ERROR_NOT_HANDLED; + case PREC_DOUBLE_TO_FLOAT: + in64 =3D get_double(t->operands[0]); + t->expected_result.val =3D float_to_u64(get_float(t->expected_resu= lt)); + res32 =3D float64_to_float32(in64, s); + break; + default: + return ERROR_NOT_HANDLED; + } + + switch (t->prec) { + case PREC_HALF_TO_DOUBLE: + case PREC_FLOAT_TO_DOUBLE: + result_is_nan =3D isnan(res64); + return tester_check(t, res64, result_is_nan, s->float_exception_fl= ags); + case PREC_HALF_TO_FLOAT: + case PREC_DOUBLE_TO_FLOAT: + result_is_nan =3D isnan(res32); + return tester_check(t, res32, result_is_nan, s->float_exception_fl= ags); + default: + assert(false); + } +} + +static enum error soft_tester_cfi(struct test_op *t, float_status *s) +{ + return ERROR_NOT_HANDLED; +} + +static enum error soft_tester_cif(struct test_op *t, float_status *s) +{ + return ERROR_NOT_HANDLED; +} + static enum error soft_tester(struct test_op *t) { float_status *s =3D &soft_status; @@ -440,6 +828,20 @@ static enum error soft_tester(struct test_op *t) s->float_rounding_mode =3D t->round; s->float_exception_flags =3D default_exceptions; =20 + /* Handle conversions first */ + switch (t->op) { + case OP_FLOAT_TO_FLOAT: + return soft_tester_cff(t, s); + case OP_FLOAT_TO_INT: + case OP_FLOAT_TO_UINT: + return soft_tester_cfi(t, s); + case OP_INT_TO_FLOAT: + case OP_UINT_TO_FLOAT: + return soft_tester_cif(t, s); + default: + break; + } + if (t->prec =3D=3D PREC_FLOAT) { float32 a, b, c; float32 *in[] =3D { &a, &b, &c }; @@ -558,17 +960,6 @@ static enum error soft_tester(struct test_op *t) return ERROR_NOT_HANDLED; } result_is_nan =3D isnan(*(double *)&res64); - } else if (t->prec =3D=3D PREC_FLOAT_TO_DOUBLE) { - float32 a =3D t->operands[0].val; - - switch (t->op) { - case OP_FLOAT_TO_DOUBLE: - res64 =3D float32_to_float64(a, s); - break; - default: - return ERROR_NOT_HANDLED; - } - result_is_nan =3D isnan(*(double *)&res64); } else { return ERROR_NOT_HANDLED; /* XXX */ } @@ -752,23 +1143,41 @@ ibm_fp_hex(const char *p, enum precision prec, struc= t operand *ret) return 0; } return 0; - } else if (!strcmp(p, "0x0")) { - if (prec =3D=3D PREC_FLOAT) { - ret->val =3D float_to_u64(0.0); - } else if (prec =3D=3D PREC_DOUBLE) { - ret->val =3D double_to_u64(0.0); - } else { - assert(false); + } else if (strncmp("0x", p, 2) =3D=3D 0) { + unsigned long long result; + char *end; + + result =3D strtoull(p, &end, 16); + if (result =3D=3D 0 && end =3D=3D p) { + /* not a number */ + return 1; + } else if (result =3D=3D ULLONG_MAX && errno) { + /* value does not fit in unsigned long long */ + return 1; + } else if (*end) { + /* began with a number but has junk left over at the end */ + return 1; } - return 0; - } else if (!strcmp(p, "0x1")) { - if (prec =3D=3D PREC_FLOAT) { - ret->val =3D float_to_u64(1.0); - } else if (prec =3D=3D PREC_DOUBLE) { - ret->val =3D double_to_u64(1.0); - } else { + + switch (prec) { + case PREC_FLOAT: + ret->val =3D float_to_u64(result); + break; + case PREC_DOUBLE: + ret->val =3D double_to_u64(result); + break; + case PREC_INT16: + case PREC_INT32: + case PREC_INT64: + case PREC_UINT16: + case PREC_UINT32: + case PREC_UINT64: + ret->val =3D result; + break; + default: assert(false); } + return 0; } return 1; @@ -814,11 +1223,14 @@ static enum error ibm_test_line(const char *line) if (unlikely(strlen(p) < 4)) { return ERROR_INPUT; } - if (strcmp("b32b64cff", p) =3D=3D 0) { - t.prec =3D PREC_FLOAT_TO_DOUBLE; + /* Conversions are of the form bXXbYYcZZ */ + if (p[0] =3D=3D 'b' && p[3] =3D=3D 'b' && p[6] =3D=3D 'c') { if (find_op(&p[6], &t.op)) { + fprintf(stderr, "%s: unhandled conversion %s\n", __func__, p); return ERROR_NOT_HANDLED; } + assert(ops[t.op].decode_tbl); + t.prec =3D decode_map_table(ops[t.op].decode_tbl, p); } else { if (strncmp("b32", p, 3) =3D=3D 0) { t.prec =3D PREC_FLOAT; @@ -855,9 +1267,7 @@ static enum error ibm_test_line(const char *line) } =20 for (i =3D 0; i < ops[t.op].n_operands; i++) { - enum precision prec =3D t.prec =3D=3D PREC_FLOAT_TO_DOUBLE ? - PREC_FLOAT : t.prec; - + enum precision prec =3D get_input_prec(t.prec); p =3D s[field++]; if (ibm_fp_hex(p, prec, &t.operands[i])) { return ERROR_INPUT; @@ -873,8 +1283,7 @@ static enum error ibm_test_line(const char *line) if (unlikely(strcmp("#", p) =3D=3D 0)) { t.expected_result_is_valid =3D false; } else { - enum precision prec =3D t.prec =3D=3D PREC_FLOAT_TO_DOUBLE ? - PREC_DOUBLE : t.prec; + enum precision prec =3D get_output_prec(t.prec); =20 if (ibm_fp_hex(p, prec, &t.expected_result)) { return ERROR_INPUT; @@ -943,7 +1352,7 @@ static void test_file(const char *filename) enum error err; =20 i++; - if (unlikely(line_is_whitelisted(line))) { + if (whitelist.n > 0 && unlikely(line_is_whitelisted(line))) { test_stats[ERROR_WHITELISTED]++; continue; } diff --git a/tests/fp/qemu/regression-tests.fptest b/tests/fp/qemu/regressi= on-tests.fptest new file mode 100644 index 0000000000..a105d3aa44 --- /dev/null +++ b/tests/fp/qemu/regression-tests.fptest @@ -0,0 +1,7 @@ +QEMU Floating point regression tests +------------------------------------ + +b32b32cfi =3D0 -Inf -> 0xffffffff80000000 i +b32b32cfi =3D0 +Inf -> 0xffffffff80000000 i +b32b64cfi =3D0 -Inf -> 0x8000000000000000 i +b32b64cfi =3D0 +Inf -> 0x8000000000000000 i --=20 2.17.0