From nobody Mon Feb 9 18:44:36 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1589413831; cv=none; d=zohomail.com; s=zohoarc; b=kPclloZPl4adXeYps+lc9Unqfo6wAeHt20RctNRhRW89VxTDw0Vq2dAtcDXH+xMOlxp/mDRlxaOgZYxsmJ6MRRNhLK/mBIo/e9ZQ/fCOaXSZxyECFoQqdgsfjgKym5TkV74uO01dKB7lscEypf3/f7N9OUB/wjBeR+Qxyf9tayw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1589413831; h=Content-Type:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=h5PxXPxBe1nXWM0PGzkzcXEMr4dEc98d+P4ltcx9r3w=; b=bkQPEHNnE49ojwkrMAL1PcCGJW6dkc7ro61N/pIW1ctSVxRy/kFrncwJqyO7q67a3C16PhVY1jVmSLmWg+A+zv/d0KStzt8C5LbRqgUdzLL0ZJ5WKmtQuhNw061UGLF5K+QZoihZefoVregA62eY/pL8ZYnN5rSsx3MA1veQurI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1589413831424105.17757229077324; Wed, 13 May 2020 16:50:31 -0700 (PDT) Received: from localhost ([::1]:47732 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jZ18w-0000EL-4L for importer@patchew.org; Wed, 13 May 2020 19:50:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50954) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jZ185-0007zo-2S for qemu-devel@nongnu.org; Wed, 13 May 2020 19:49:37 -0400 Received: from esa3.mentor.iphmx.com ([68.232.137.180]:57185) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jZ183-0001nb-Ma for qemu-devel@nongnu.org; Wed, 13 May 2020 19:49:36 -0400 Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 13 May 2020 15:49:33 -0800 IronPort-SDR: RFcFTjgM5CyrE+T+tNxVvScx2f+vR9dJzuMB9FuLgBCBwCxBRyIdEpURwZXrWwoLkvR43s8F3V lBPlLpWbNTZVuKDUf6nOnW/++3AFmGZ9EKt4fCjzQQPbKU1ikR8Sb+qqYbvfUAa3ZUxd80OlTj 2NqAlkFN8ZgNAitSNKsM6OQo/gXTwjyEFH265d/OvP8UzVmWEv5gDKp4/YC4NUqNhI9A3HjxEY 1eRH9AW226Elxy287R88vWAoFud8xoqB4llLAUt0FNIZNdqhf/vQcFEyvj1Sc+5zQPvi0XJtPA hm8= X-IronPort-AV: E=Sophos;i="5.73,389,1583222400"; d="scan'208";a="48823184" IronPort-SDR: bzphfi7peCmMi8TXG2X/RmTB++nbU4ff5bQuU/baxOMosWKOiP6r/tjjjP1x6PHwlwfctStyCz vUsFkAWf1r76WBnUaZbaUEpbWZg4OjV0OMFNPZT1M/t1yXWj7XrppYres4UPcMYXw0VghbGr61 UDgEoWhNmVnF4hKzx+rz7eBzlsHYTgmVuQx0j9jwqyBvjYHVVpT+oorDmSdi2KtmtkYDojbWNo bQQ+1tb0ZB3mUKams6rSrwbkAMkeDFgGTLjl5uCIyCw8wURqDzODmq3g6WOEUMcfp2j5/W6CST L2o= Date: Wed, 13 May 2020 23:49:27 +0000 From: Joseph Myers X-X-Sender: jsm28@digraph.polyomino.org.uk To: , , , Subject: [PATCH 1/4] target/i386: fix floating-point load-constant rounding In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) To svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=68.232.137.180; envelope-from=joseph_myers@mentor.com; helo=esa3.mentor.iphmx.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/13 19:49:34 X-ACL-Warn: Detected OS = FreeBSD 9.x or newer [fuzzy] X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The implementations of the fldl2t, fldl2e, fldpi, fldlg2 and fldln2 instructions load fixed constants independent of the rounding mode. Fix them to load a value correctly rounded for the current rounding mode (but always rounded to 64-bit precision independent of the precision control, and without setting "inexact") as specified. Signed-off-by: Joseph Myers Reviewed-by: Richard Henderson --- target/i386/fpu_helper.c | 54 +++++++- tests/tcg/i386/test-i386-fldcst.c | 199 ++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+), 5 deletions(-) create mode 100644 tests/tcg/i386/test-i386-fldcst.c diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index 0c3fce933c..38968b2ec7 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -59,8 +59,13 @@ #define FPUC_EM 0x3f =20 #define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL) +#define floatx80_lg2_d make_floatx80(0x3ffd, 0x9a209a84fbcff798LL) #define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL) +#define floatx80_l2e_d make_floatx80(0x3fff, 0xb8aa3b295c17f0bbLL) #define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL) +#define floatx80_l2t_u make_floatx80(0x4000, 0xd49a784bcd1b8affLL) +#define floatx80_ln2_d make_floatx80(0x3ffe, 0xb17217f7d1cf79abLL) +#define floatx80_pi_d make_floatx80(0x4000, 0xc90fdaa22168c234LL) =20 #if !defined(CONFIG_USER_ONLY) static qemu_irq ferr_irq; @@ -544,27 +549,66 @@ void helper_fld1_ST0(CPUX86State *env) =20 void helper_fldl2t_ST0(CPUX86State *env) { - ST0 =3D floatx80_l2t; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_UP: + ST0 =3D floatx80_l2t_u; + break; + default: + ST0 =3D floatx80_l2t; + break; + } } =20 void helper_fldl2e_ST0(CPUX86State *env) { - ST0 =3D floatx80_l2e; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 =3D floatx80_l2e_d; + break; + default: + ST0 =3D floatx80_l2e; + break; + } } =20 void helper_fldpi_ST0(CPUX86State *env) { - ST0 =3D floatx80_pi; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 =3D floatx80_pi_d; + break; + default: + ST0 =3D floatx80_pi; + break; + } } =20 void helper_fldlg2_ST0(CPUX86State *env) { - ST0 =3D floatx80_lg2; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 =3D floatx80_lg2_d; + break; + default: + ST0 =3D floatx80_lg2; + break; + } } =20 void helper_fldln2_ST0(CPUX86State *env) { - ST0 =3D floatx80_ln2; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 =3D floatx80_ln2_d; + break; + default: + ST0 =3D floatx80_ln2; + break; + } } =20 void helper_fldz_ST0(CPUX86State *env) diff --git a/tests/tcg/i386/test-i386-fldcst.c b/tests/tcg/i386/test-i386-f= ldcst.c new file mode 100644 index 0000000000..e635432ccf --- /dev/null +++ b/tests/tcg/i386/test-i386-fldcst.c @@ -0,0 +1,199 @@ +/* Test instructions loading floating-point constants. */ + +#include +#include + +volatile long double ld_res; + +int main(void) +{ + short cw; + int ret =3D 0; + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t N\n"); + ret =3D 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t D\n"); + ret =3D 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t Z\n"); + ret =3D 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.5269e12f346e2bfcp+0L) { + printf("FAIL: fldl2t U\n"); + ret =3D 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x1.71547652b82fe178p+0L) { + printf("FAIL: fldl2e N\n"); + ret =3D 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x1.71547652b82fe176p+0L) { + printf("FAIL: fldl2e D\n"); + ret =3D 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x1.71547652b82fe176p+0L) { + printf("FAIL: fldl2e Z\n"); + ret =3D 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x1.71547652b82fe178p+0L) { + printf("FAIL: fldl2e U\n"); + ret =3D 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.243f6a8885a308d4p+0L) { + printf("FAIL: fldpi N\n"); + ret =3D 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.243f6a8885a308dp+0L) { + printf("FAIL: fldpi D\n"); + ret =3D 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.243f6a8885a308dp+0L) { + printf("FAIL: fldpi Z\n"); + ret =3D 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x3.243f6a8885a308d4p+0L) { + printf("FAIL: fldpi U\n"); + ret =3D 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x4.d104d427de7fbcc8p-4L) { + printf("FAIL: fldlg2 N\n"); + ret =3D 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x4.d104d427de7fbccp-4L) { + printf("FAIL: fldlg2 D\n"); + ret =3D 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x4.d104d427de7fbccp-4L) { + printf("FAIL: fldlg2 Z\n"); + ret =3D 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0x4.d104d427de7fbcc8p-4L) { + printf("FAIL: fldlg2 U\n"); + ret =3D 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0xb.17217f7d1cf79acp-4L) { + printf("FAIL: fldln2 N\n"); + ret =3D 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0xb.17217f7d1cf79abp-4L) { + printf("FAIL: fldln2 D\n"); + ret =3D 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0xb.17217f7d1cf79abp-4L) { + printf("FAIL: fldln2 Z\n"); + ret =3D 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=3Dm" (cw)); + cw =3D (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=3Dt" (ld_res)); + if (ld_res !=3D 0xb.17217f7d1cf79acp-4L) { + printf("FAIL: fldln2 U\n"); + ret =3D 1; + } + + return ret; +} --=20 2.17.1 --=20 Joseph S. Myers joseph@codesourcery.com