From nobody Sat May 4 15:20:10 2024 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.zoho.com; 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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497992035906370.1294878715262; Tue, 20 Jun 2017 13:53:55 -0700 (PDT) Received: from localhost ([::1]:50611 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ9o-0001Lb-Ti for importer@patchew.org; Tue, 20 Jun 2017 16:53:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55329) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ7z-0008AD-KA for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dNQ7u-0004C3-RN for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:51:59 -0400 Received: from mout.kundenserver.de ([212.227.17.13]:65270) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dNQ7u-0004BV-Gp for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:51:54 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0MekDA-1d86A12Ong-00OHN7; Tue, 20 Jun 2017 22:51:25 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Tue, 20 Jun 2017 22:51:16 +0200 Message-Id: <20170620205121.26515-2-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170620205121.26515-1-laurent@vivier.eu> References: <20170620205121.26515-1-laurent@vivier.eu> X-Provags-ID: V03:K0:E2HMgsM9ey8TRXeZGHpIDdqyZ+yLE9tCiNEZFSOJW5pnAXK7Kdi OaLMS2SeFNhtD4KtB1ZJKY/9n+3lzkFUvbwBNV30T16Es80YkjRJ2sFgV9aiLi64kslW8f8 el7qjmgix/c7Zt06l5rsyqQqA9bF5GqMKDh3LjJrtvVh4dcSwco7/pWaFuvotgknfRxJrOP 20K3odzPUKKSvsmpIH6Rg== X-UI-Out-Filterresults: notjunk:1;V01:K0:DjWydL0t6jw=:liTvDadQCg6BHjs9c3tc2s siv2BH3OQpVbFpxCiViCEZgorbflvDitqYJ/lnQVnO2q4AvBtk81KWKAuSjkgPSzKdvaUnaCR uUoLNZJs/LloLGGQLg/C11p4fALLHdyHiv+pJ7u5oghVFQUVc77bcrtjIPJxoZOgDet1YqPvd 49VTpvpGpg6RJ6BUoRSzToLJ4RgHy/pP5CV4UqU86+6NFDI2rRQMlWxM5BYOq25xuN3nc4BIy hQL0cyjZZZC6my+ta4QasTtj23cog5Y+tQ6PQbVXMfqgjBFWa5m/neIrGGx4qHkheWq+IH7Po /RqC080DomK2Yl46jfvlAmBLeEKh6kZJ4aEfnDwfDw1pzgeXRE8Encoel1ZEbde0e5RAFnZgi xVzk0eRfanYviDnpXRE5kyE7CDDJPzJAZRWJ55fyAKwCqUS08VbXS1Mxydy91S3JfE0FvHW7I iwt6HkKXYkQBhO13j7Fg83NEqjU+n6eyyhNNHwudzWsz2xBysY2qcgP1cGiBD+zwDvHskJv3v 3IKpkjZJ4m83Hck6EQWN/ZN6JtvwGkJFWZfWUXUUhrSsERzWN2UZcrahA+WDudMIjiMjKNY/8 lWJxZsghQ1MtqO/KvmbqS41EakG+++tUe8dTfxeD4I98LTg0vzrsLrWWSAaKME+bxqIuSq+zD 05PN3GaIXgyzTTgOGV8JgvWV2Wyesfy94RZjfY5SolsTkQO002dpdMeztZMaJ4S34LSE= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.13 Subject: [Qemu-devel] [PATCH v5 1/6] target-m68k: move fmove CR to a function 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: Thomas Huth , Riku Voipio , Laurent Vivier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Move code of fmove to/from control register to a function Signed-off-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Richard Henderson --- target/m68k/translate.c | 56 +++++++++++++++++++++++++++------------------= ---- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index dfecfb6..c9a5fe4 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4099,6 +4099,35 @@ DISAS_INSN(trap) gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf)); } =20 +static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s, + uint32_t insn, uint32_t ext) +{ + int mask =3D (ext >> 10) & 7; + int is_write =3D (ext >> 13) & 1; + TCGv val; + + switch (mask) { + case 1: /* FPIAR */ + case 2: /* FPSR */ + default: + qemu_log_mask(LOG_UNIMP, "Unimplemented: fmove to/from control %d", + mask); + goto undef; + case 4: /* FPCR */ + if (is_write) { + val =3D tcg_const_i32(0); + DEST_EA(env, insn, OS_LONG, val, NULL); + tcg_temp_free(val); + } + /* Not implemented. Ignore register update */ + break; + } + return; +undef: + s->pc -=3D 2; + disas_undef_fpu(env, s, insn); +} + /* ??? FP exceptions are not implemented. Most exceptions are deferred un= til immediately before the next FP instruction is executed. */ DISAS_INSN(fpu) @@ -4177,32 +4206,9 @@ DISAS_INSN(fpu) tcg_temp_free_i32(tmp32); return; case 4: /* fmove to control register. */ - switch ((ext >> 10) & 7) { - case 4: /* FPCR */ - /* Not implemented. Ignore writes. */ - break; - case 1: /* FPIAR */ - case 2: /* FPSR */ - default: - cpu_abort(NULL, "Unimplemented: fmove to control %d", - (ext >> 10) & 7); - } - break; case 5: /* fmove from control register. */ - switch ((ext >> 10) & 7) { - case 4: /* FPCR */ - /* Not implemented. Always return zero. */ - tmp32 =3D tcg_const_i32(0); - break; - case 1: /* FPIAR */ - case 2: /* FPSR */ - default: - cpu_abort(NULL, "Unimplemented: fmove from control %d", - (ext >> 10) & 7); - goto undef; - } - DEST_EA(env, insn, OS_LONG, tmp32, NULL); - break; + gen_op_fmove_fcr(env, s, insn, ext); + return; case 6: /* fmovem */ case 7: { --=20 2.9.4 From nobody Sat May 4 15:20:10 2024 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.zoho.com; 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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497992050634737.1111244691516; Tue, 20 Jun 2017 13:54:10 -0700 (PDT) Received: from localhost ([::1]:50614 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQA4-0001Ys-NF for importer@patchew.org; Tue, 20 Jun 2017 16:54:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55428) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ87-0008EJ-0Q for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dNQ82-0004Ff-DG for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:07 -0400 Received: from mout.kundenserver.de ([212.227.17.24]:52245) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dNQ82-0004F2-3B for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:02 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0M5gVc-1dh9ra1oPA-00xcBp; Tue, 20 Jun 2017 22:51:26 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Tue, 20 Jun 2017 22:51:17 +0200 Message-Id: <20170620205121.26515-3-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170620205121.26515-1-laurent@vivier.eu> References: <20170620205121.26515-1-laurent@vivier.eu> X-Provags-ID: V03:K0:obBHzNvW891xuMjMOkkdNY3jWNtiP3YYVTRXbBahiTj2VN0Uid3 qY6dO0H1CpRq0UdRpZx5HA7Vn6Xxik4E3KhXwgajtsahGU4mBFGZjsgYvyYohqy08HKw+N8 HhcOSV4tXrHvBIU01rpCsSHV/095tBe1iN8aHYYRIUg4pXQUgNxmfn8WZNtm03FfTq7j/Pj ZwPEmXB1L7z6xw87Ng/eg== X-UI-Out-Filterresults: notjunk:1;V01:K0:ssbU1zLMS5M=:az0pcYUy9Pt4BtheaEBUda rTGFrtBwRaaKku/BGy1ogLcONjFyqiJaLRPABdTM6emGs11MSV2ikEhxYQP0VxJvH0J0Zus5h n7iUqVbQybvf1X08RX+VuNHF9YcIdC72btIYI/Qi14tdpviM/WjfE8OpO+Kt1ijCENPevoe5Q 3rJHgOyHD6JJtAEutZffN3lV/7mHr7TArE07THuS++ZeloBWvxDtoaTNOGMqx3Y8gTVmNUQUj 33Qw3HEOQFRvjDWLF3bAVgG0QVB3hwhucHE2bAeZIMWJ6pjZ7T1XCJRkIdrWZ5vO3C716uTYL MLM+zsMtG2WyVtE1tocPjSgUb2lQ3LnnYMH9Ydqehhj57/Tii74ICM7BQqQj9WTC8cGp/UFOY 7j48ZxRRTM/xppatZEhs1SE0wDkINGAZL/0jOqMU+qENLSNM7b1H0j5JNUfoeUmqKei7RLfBy MbBdWWWxaXykgzkAYL9tLbHUDrWPFBODjsn+HZfKPE5drygiCIhbbXSPex4/7TgmAqJm0Ymzi OLqpRF9LFbZAJyBpKdJRuezVSJupdMfyxvv8Zmy8gzI5krkp5izcsyp6304c9U2EHxa4mptCh yRLUo2wDLjS2iQuktS4eloRgPp6Vnrbp1AiQBEtUmPhDqpaohGYmv+02cnEnhHN/yOtdiFigx W8zLh3qe28C3ncK0pczSZmeIAMvxzrCCf9t+uuwQDiXYtyBGkvd/5Rs4fDikmlfZMqiM= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.24 Subject: [Qemu-devel] [PATCH v5 2/6] target-m68k: initialize FPU registers 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: Thomas Huth , Riku Voipio , Laurent Vivier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" on reset, set FP registers to NaN and control registers to 0 Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson --- target/m68k/cpu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index f068922..f2e031f 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -49,6 +49,8 @@ static void m68k_cpu_reset(CPUState *s) M68kCPU *cpu =3D M68K_CPU(s); M68kCPUClass *mcc =3D M68K_CPU_GET_CLASS(cpu); CPUM68KState *env =3D &cpu->env; + float64 nan =3D float64_default_nan(NULL); + int i; =20 mcc->parent_reset(s); =20 @@ -57,7 +59,12 @@ static void m68k_cpu_reset(CPUState *s) env->sr =3D 0x2700; #endif m68k_switch_sp(env); - /* ??? FP regs should be initialized to NaN. */ + for (i =3D 0; i < 8; i++) { + env->fregs[i] =3D nan; + } + env->fpcr =3D 0; + env->fpsr =3D 0; + cpu_m68k_set_ccr(env, 0); /* TODO: We should set PC from the interrupt vector. */ env->pc =3D 0; --=20 2.9.4 From nobody Sat May 4 15:20:10 2024 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.zoho.com; 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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497992246995335.4062929768969; Tue, 20 Jun 2017 13:57:26 -0700 (PDT) Received: from localhost ([::1]:50631 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQDF-0003pX-DH for importer@patchew.org; Tue, 20 Jun 2017 16:57:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55507) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ8L-0008VN-Rh for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dNQ8H-0004Lq-5U for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:21 -0400 Received: from mout.kundenserver.de ([212.227.17.13]:60869) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dNQ8G-0004LZ-IO for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:17 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0MK1VF-1dOFb81GFh-001OOO; Tue, 20 Jun 2017 22:51:28 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Tue, 20 Jun 2017 22:51:18 +0200 Message-Id: <20170620205121.26515-4-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170620205121.26515-1-laurent@vivier.eu> References: <20170620205121.26515-1-laurent@vivier.eu> X-Provags-ID: V03:K0:mJVGUVYFejhiUQd6fZRqZ+03Dw/t39GN85YGK6rPYR8qL6ZOUfC PJ40OLixhJO2zEzl5vGHZD52fQRI7kOP5thL0zk5e/krpBbVY8f2numTl3Sbazz+ktJOs31 UelgQejKomG89jKHNblvZrWoQiLHulcJu00FKWSszdRONzX9RW9z8z4OHqpiQizmnU2dtiT bIDhCOgjxgijhjrE25Wbg== X-UI-Out-Filterresults: notjunk:1;V01:K0:kCOgb36x6XQ=:MDwgXzc7/O9mjWtjipp1qe 9pN1MM1bvzwgjhZjcM9QX3sgXvyezoxTiP/X34OJXEgAaGN9zhXR+HF5nLHUYpRujc6DePwLh d8hwQ2A6aXoIosR8cwGACy/aO3kOBm5I9F16kOnh6w9bHeniYVw65BuHc0WaN5bORgmZYtJPp jXMAjacBHwMW0e6Ix/lVPkGdN2cdPyfPAjuXpliG+/HZEH6m0+nLCJRnCXleHWcbzceG13VrU L2ZfWgQErXlDBhOxNFdQ6gm+28YERiVZ2AvHe0h7c37WNsBD7p3UQckJ/DWkh94HMSR3AmVec zHW1QGi2S3WJyhYkDC1BnQpHvBrDRmiq6G8FP19YW+hxLaGFNarhKMyY+zlteZ5+M87CErHmz nsP5wBksZbrdPOeCQIhHadTGC3rHvzCtzLRMNzjmmHlslKbGOCR2B/amDOS6a5zNKZpbvpLfN e0B5QrgDLOo1gEA/xCyKRhxQzO2CCC8i/Fk1SbbPDIgGxvJ3aeB0qI81BcjZUNLkIfwQUJbm7 gnYJv3YeTdbCuU+hVcG7bn5CA22uDyR0IeuZ+syUA4pAbPJGpUwl8ZxBy1y+BzEgkl4Tu4piH 2XI6lXcqRnk0/bNasamkosLwu/G7jxKWhEApZviSdr5bvoJSDlg0IKpMuMhEORbGksnoJRT8Q aCrT36z2GlUEePYGneyn1iJhNMMa2sIecS8NXJQAohxQR7Pn5R7+gCZNhiuMrJ4KC3FQ= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.13 Subject: [Qemu-devel] [PATCH v5 3/6] target-m68k: use floatx80 internally 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: Thomas Huth , Riku Voipio , Laurent Vivier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Coldfire uses float64, but 680x0 use floatx80. This patch introduces the use of floatx80 internally and enables 680x0 80bits FPU. Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson --- target/m68k/cpu.c | 4 +- target/m68k/cpu.h | 15 +- target/m68k/fpu_helper.c | 85 ++++--- target/m68k/helper.c | 12 +- target/m68k/helper.h | 37 +-- target/m68k/qregs.def | 1 - target/m68k/translate.c | 646 ++++++++++++++++++++++++++++++-------------= ---- 7 files changed, 509 insertions(+), 291 deletions(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index f2e031f..435456f 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -49,7 +49,7 @@ static void m68k_cpu_reset(CPUState *s) M68kCPU *cpu =3D M68K_CPU(s); M68kCPUClass *mcc =3D M68K_CPU_GET_CLASS(cpu); CPUM68KState *env =3D &cpu->env; - float64 nan =3D float64_default_nan(NULL); + floatx80 nan =3D floatx80_default_nan(NULL); int i; =20 mcc->parent_reset(s); @@ -60,7 +60,7 @@ static void m68k_cpu_reset(CPUState *s) #endif m68k_switch_sp(env); for (i =3D 0; i < 8; i++) { - env->fregs[i] =3D nan; + env->fregs[i].d =3D nan; } env->fpcr =3D 0; env->fpsr =3D 0; diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 384ec5d..beb8ebc 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -55,8 +55,15 @@ #define EXCP_UNINITIALIZED 15 #define EXCP_TRAP0 32 /* User trap #0. */ #define EXCP_TRAP15 47 /* User trap #15. */ +#define EXCP_FP_BSUN 48 /* Branch Set on Unordered */ +#define EXCP_FP_INEX 49 /* Inexact result */ +#define EXCP_FP_DZ 50 /* Divide by Zero */ +#define EXCP_FP_UNFL 51 /* Underflow */ +#define EXCP_FP_OPERR 52 /* Operand Error */ +#define EXCP_FP_OVFL 53 /* Overflow */ +#define EXCP_FP_SNAN 54 /* Signaling Not-A-Number */ +#define EXCP_FP_UNIMP 55 /* Unimplemented Data type */ #define EXCP_UNSUPPORTED 61 -#define EXCP_ICE 13 =20 #define EXCP_RTE 0x100 #define EXCP_HALT_INSN 0x101 @@ -64,6 +71,8 @@ #define NB_MMU_MODES 2 #define TARGET_INSN_START_EXTRA_WORDS 1 =20 +typedef CPU_LDoubleU FPReg; + typedef struct CPUM68KState { uint32_t dregs[8]; uint32_t aregs[8]; @@ -82,8 +91,8 @@ typedef struct CPUM68KState { uint32_t cc_c; /* either 0/1, unused, or computed from cc_n and cc_v */ uint32_t cc_z; /* =3D=3D 0 or unused */ =20 - float64 fregs[8]; - float64 fp_result; + FPReg fregs[8]; + FPReg fp_result; uint32_t fpcr; uint32_t fpsr; float_status fp_status; diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index 5bf2576..f4d3821 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -21,92 +21,101 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "exec/exec-all.h" =20 -uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val) +int32_t HELPER(reds32)(CPUM68KState *env, FPReg *val) { - return float64_to_int32(val, &env->fp_status); + return floatx80_to_int32(val->d, &env->fp_status); } =20 -float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val) +float32 HELPER(redf32)(CPUM68KState *env, FPReg *val) { - return float64_to_float32(val, &env->fp_status); + return floatx80_to_float32(val->d, &env->fp_status); } =20 -float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val) +void HELPER(exts32)(CPUM68KState *env, FPReg *res, int32_t val) { - return int32_to_float64(val, &env->fp_status); + res->d =3D int32_to_floatx80(val, &env->fp_status); } =20 -float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val) +void HELPER(extf32)(CPUM68KState *env, FPReg *res, float32 val) { - return float32_to_float64(val, &env->fp_status); + res->d =3D float32_to_floatx80(val, &env->fp_status); } =20 -float64 HELPER(iround_f64)(CPUM68KState *env, float64 val) +void HELPER(extf64)(CPUM68KState *env, FPReg *res, float64 val) { - return float64_round_to_int(val, &env->fp_status); + res->d =3D float64_to_floatx80(val, &env->fp_status); } =20 -float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val) +float64 HELPER(redf64)(CPUM68KState *env, FPReg *val) { - return float64_trunc_to_int(val, &env->fp_status); + return floatx80_to_float64(val->d, &env->fp_status); } =20 -float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val) +void HELPER(firound)(CPUM68KState *env, FPReg *res, FPReg *val) { - return float64_sqrt(val, &env->fp_status); + res->d =3D floatx80_round_to_int(val->d, &env->fp_status); } =20 -float64 HELPER(abs_f64)(float64 val) +void HELPER(fitrunc)(CPUM68KState *env, FPReg *res, FPReg *val) { - return float64_abs(val); + res->d =3D floatx80_round_to_int(val->d, &env->fp_status); } =20 -float64 HELPER(chs_f64)(float64 val) +void HELPER(fsqrt)(CPUM68KState *env, FPReg *res, FPReg *val) { - return float64_chs(val); + res->d =3D floatx80_sqrt(val->d, &env->fp_status); } =20 -float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b) +void HELPER(fabs)(CPUM68KState *env, FPReg *res, FPReg *val) { - return float64_add(a, b, &env->fp_status); + res->d =3D floatx80_abs(val->d); } =20 -float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b) +void HELPER(fchs)(CPUM68KState *env, FPReg *res, FPReg *val) { - return float64_sub(a, b, &env->fp_status); + res->d =3D floatx80_chs(val->d); } =20 -float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b) +void HELPER(fadd)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) { - return float64_mul(a, b, &env->fp_status); + res->d =3D floatx80_add(val0->d, val1->d, &env->fp_status); } =20 -float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b) +void HELPER(fsub)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) { - return float64_div(a, b, &env->fp_status); + res->d =3D floatx80_sub(val1->d, val0->d, &env->fp_status); } =20 -float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b) +void HELPER(fmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) +{ + res->d =3D floatx80_mul(val0->d, val1->d, &env->fp_status); +} + +void HELPER(fdiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1) +{ + res->d =3D floatx80_div(val1->d, val0->d, &env->fp_status); +} + +void HELPER(fsub_cmp)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *v= al1) { /* ??? This may incorrectly raise exceptions. */ /* ??? Should flush denormals to zero. */ - float64 res; - res =3D float64_sub(a, b, &env->fp_status); - if (float64_is_quiet_nan(res, &env->fp_status)) { + res->d =3D floatx80_sub(val0->d, val1->d, &env->fp_status); + if (floatx80_is_quiet_nan(res->d, &env->fp_status)) { /* +/-inf compares equal against itself, but sub returns nan. */ - if (!float64_is_quiet_nan(a, &env->fp_status) - && !float64_is_quiet_nan(b, &env->fp_status)) { - res =3D float64_zero; - if (float64_lt_quiet(a, res, &env->fp_status)) { - res =3D float64_chs(res); + if (!floatx80_is_quiet_nan(val0->d, &env->fp_status) + && !floatx80_is_quiet_nan(val1->d, &env->fp_status)) { + res->d =3D floatx80_zero; + if (floatx80_lt_quiet(val0->d, res->d, &env->fp_status)) { + res->d =3D floatx80_chs(res->d); } } } - return res; } =20 -uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val) +uint32_t HELPER(fcompare)(CPUM68KState *env, FPReg *val) { - return float64_compare_quiet(val, float64_zero, &env->fp_status); + return floatx80_compare_quiet(val->d, floatx80_zero, &env->fp_status); } diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 5ca9911..8bfc881 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -73,10 +73,11 @@ void m68k_cpu_list(FILE *f, fprintf_function cpu_fprint= f) g_slist_free(list); } =20 -static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n) +static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n) { if (n < 8) { - stfq_p(mem_buf, env->fregs[n]); + float_status s; + stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s)); return 8; } if (n < 11) { @@ -87,10 +88,11 @@ static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *= mem_buf, int n) return 0; } =20 -static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n) +static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n) { if (n < 8) { - env->fregs[n] =3D ldfq_p(mem_buf); + float_status s; + env->fregs[n].d =3D float64_to_floatx80(ldfq_p(mem_buf), &s); return 8; } if (n < 11) { @@ -126,7 +128,7 @@ void m68k_cpu_init_gdb(M68kCPU *cpu) CPUM68KState *env =3D &cpu->env; =20 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) { - gdb_register_coprocessor(cs, fpu_gdb_get_reg, fpu_gdb_set_reg, + gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_re= g, 11, "cf-fp.xml", 18); } /* TODO: Add [E]MAC registers. */ diff --git a/target/m68k/helper.h b/target/m68k/helper.h index d7a4bf1..d871be6 100644 --- a/target/m68k/helper.h +++ b/target/m68k/helper.h @@ -12,21 +12,28 @@ DEF_HELPER_3(movec, void, env, i32, i32) DEF_HELPER_4(cas2w, void, env, i32, i32, i32) DEF_HELPER_4(cas2l, void, env, i32, i32, i32) =20 -DEF_HELPER_2(f64_to_i32, f32, env, f64) -DEF_HELPER_2(f64_to_f32, f32, env, f64) -DEF_HELPER_2(i32_to_f64, f64, env, i32) -DEF_HELPER_2(f32_to_f64, f64, env, f32) -DEF_HELPER_2(iround_f64, f64, env, f64) -DEF_HELPER_2(itrunc_f64, f64, env, f64) -DEF_HELPER_2(sqrt_f64, f64, env, f64) -DEF_HELPER_1(abs_f64, f64, f64) -DEF_HELPER_1(chs_f64, f64, f64) -DEF_HELPER_3(add_f64, f64, env, f64, f64) -DEF_HELPER_3(sub_f64, f64, env, f64, f64) -DEF_HELPER_3(mul_f64, f64, env, f64, f64) -DEF_HELPER_3(div_f64, f64, env, f64, f64) -DEF_HELPER_3(sub_cmp_f64, f64, env, f64, f64) -DEF_HELPER_2(compare_f64, i32, env, f64) +#define dh_alias_fp ptr +#define dh_ctype_fp FPReg * +#define dh_is_signed_fp dh_is_signed_ptr + +DEF_HELPER_3(exts32, void, env, fp, s32) +DEF_HELPER_3(extf32, void, env, fp, f32) +DEF_HELPER_3(extf64, void, env, fp, f64) +DEF_HELPER_2(redf32, f32, env, fp) +DEF_HELPER_2(redf64, f64, env, fp) +DEF_HELPER_2(reds32, s32, env, fp) + +DEF_HELPER_3(firound, void, env, fp, fp) +DEF_HELPER_3(fitrunc, void, env, fp, fp) +DEF_HELPER_3(fsqrt, void, env, fp, fp) +DEF_HELPER_3(fabs, void, env, fp, fp) +DEF_HELPER_3(fchs, void, env, fp, fp) +DEF_HELPER_4(fadd, void, env, fp, fp, fp) +DEF_HELPER_4(fsub, void, env, fp, fp, fp) +DEF_HELPER_4(fmul, void, env, fp, fp, fp) +DEF_HELPER_4(fdiv, void, env, fp, fp, fp) +DEF_HELPER_4(fsub_cmp, void, env, fp, fp, fp) +DEF_HELPER_2(fcompare, i32, env, fp) =20 DEF_HELPER_3(mac_move, void, env, i32, i32) DEF_HELPER_3(macmulf, i64, env, i32, i32) diff --git a/target/m68k/qregs.def b/target/m68k/qregs.def index 51ff43b..1aadc62 100644 --- a/target/m68k/qregs.def +++ b/target/m68k/qregs.def @@ -1,4 +1,3 @@ -DEFF64(FP_RESULT, fp_result) DEFO32(PC, pc) DEFO32(SR, sr) DEFO32(CC_OP, cc_op) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index c9a5fe4..73f691f 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -32,37 +32,27 @@ #include "trace-tcg.h" #include "exec/log.h" =20 - //#define DEBUG_DISPATCH 1 =20 -/* Fake floating point. */ -#define tcg_gen_mov_f64 tcg_gen_mov_i64 -#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64 -#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64 - #define DEFO32(name, offset) static TCGv QREG_##name; #define DEFO64(name, offset) static TCGv_i64 QREG_##name; -#define DEFF64(name, offset) static TCGv_i64 QREG_##name; #include "qregs.def" #undef DEFO32 #undef DEFO64 -#undef DEFF64 =20 static TCGv_i32 cpu_halted; static TCGv_i32 cpu_exception_index; =20 static TCGv_env cpu_env; =20 -static char cpu_reg_names[3*8*3 + 5*4]; +static char cpu_reg_names[2 * 8 * 3 + 5 * 4]; static TCGv cpu_dregs[8]; static TCGv cpu_aregs[8]; -static TCGv_i64 cpu_fregs[8]; static TCGv_i64 cpu_macc[4]; =20 #define REG(insn, pos) (((insn) >> (pos)) & 7) #define DREG(insn, pos) cpu_dregs[REG(insn, pos)] #define AREG(insn, pos) get_areg(s, REG(insn, pos)) -#define FREG(insn, pos) cpu_fregs[REG(insn, pos)] #define MACREG(acc) cpu_macc[acc] #define QREG_SP get_areg(s, 7) =20 @@ -87,11 +77,9 @@ void m68k_tcg_init(void) #define DEFO64(name, offset) \ QREG_##name =3D tcg_global_mem_new_i64(cpu_env, \ offsetof(CPUM68KState, offset), #name); -#define DEFF64(name, offset) DEFO64(name, offset) #include "qregs.def" #undef DEFO32 #undef DEFO64 -#undef DEFF64 =20 cpu_halted =3D tcg_global_mem_new_i32(cpu_env, -offsetof(M68kCPU, env) + @@ -111,10 +99,6 @@ void m68k_tcg_init(void) cpu_aregs[i] =3D tcg_global_mem_new(cpu_env, offsetof(CPUM68KState, aregs[i])= , p); p +=3D 3; - sprintf(p, "F%d", i); - cpu_fregs[i] =3D tcg_global_mem_new_i64(cpu_env, - offsetof(CPUM68KState, fregs[i])= , p); - p +=3D 3; } for (i =3D 0; i < 4; i++) { sprintf(p, "ACC%d", i); @@ -265,6 +249,42 @@ static void update_cc_op(DisasContext *s) } } =20 +/* Generate a jump to an immediate address. */ +static void gen_jmp_im(DisasContext *s, uint32_t dest) +{ + update_cc_op(s); + tcg_gen_movi_i32(QREG_PC, dest); + s->is_jmp =3D DISAS_JUMP; +} + +/* Generate a jump to the address in qreg DEST. */ +static void gen_jmp(DisasContext *s, TCGv dest) +{ + update_cc_op(s); + tcg_gen_mov_i32(QREG_PC, dest); + s->is_jmp =3D DISAS_JUMP; +} + +static void gen_raise_exception(int nr) +{ + TCGv_i32 tmp =3D tcg_const_i32(nr); + + gen_helper_raise_exception(cpu_env, tmp); + tcg_temp_free_i32(tmp); +} + +static void gen_exception(DisasContext *s, uint32_t where, int nr) +{ + update_cc_op(s); + gen_jmp_im(s, where); + gen_raise_exception(nr); +} + +static inline void gen_addr_fault(DisasContext *s) +{ + gen_exception(s, s->insn_pc, EXCP_ADDRESS); +} + /* Generate a load from the specified address. Narrow values are sign extended to full register width. */ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int s= ign) @@ -286,7 +306,6 @@ static inline TCGv gen_load(DisasContext * s, int opsiz= e, TCGv addr, int sign) tcg_gen_qemu_ld16u(tmp, addr, index); break; case OS_LONG: - case OS_SINGLE: tcg_gen_qemu_ld32u(tmp, addr, index); break; default: @@ -296,16 +315,6 @@ static inline TCGv gen_load(DisasContext * s, int opsi= ze, TCGv addr, int sign) return tmp; } =20 -static inline TCGv_i64 gen_load64(DisasContext * s, TCGv addr) -{ - TCGv_i64 tmp; - int index =3D IS_USER(s); - tmp =3D tcg_temp_new_i64(); - tcg_gen_qemu_ldf64(tmp, addr, index); - gen_throws_exception =3D gen_last_qop; - return tmp; -} - /* Generate a store. */ static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv = val) { @@ -318,7 +327,6 @@ static inline void gen_store(DisasContext *s, int opsiz= e, TCGv addr, TCGv val) tcg_gen_qemu_st16(val, addr, index); break; case OS_LONG: - case OS_SINGLE: tcg_gen_qemu_st32(val, addr, index); break; default: @@ -327,13 +335,6 @@ static inline void gen_store(DisasContext *s, int opsi= ze, TCGv addr, TCGv val) gen_throws_exception =3D gen_last_qop; } =20 -static inline void gen_store64(DisasContext *s, TCGv addr, TCGv_i64 val) -{ - int index =3D IS_USER(s); - tcg_gen_qemu_stf64(val, addr, index); - gen_throws_exception =3D gen_last_qop; -} - typedef enum { EA_STORE, EA_LOADU, @@ -377,6 +378,15 @@ static inline uint32_t read_im32(CPUM68KState *env, Di= sasContext *s) return im; } =20 +/* Read a 64-bit immediate constant. */ +static inline uint64_t read_im64(CPUM68KState *env, DisasContext *s) +{ + uint64_t im; + im =3D (uint64_t)read_im32(env, s) << 32; + im |=3D (uint64_t)read_im32(env, s); + return im; +} + /* Calculate and address index. */ static TCGv gen_addr_index(DisasContext *s, uint16_t ext, TCGv tmp) { @@ -909,6 +919,304 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s= , uint16_t insn, return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what); } =20 +static TCGv_ptr gen_fp_ptr(int freg) +{ + TCGv_ptr fp =3D tcg_temp_new_ptr(); + tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fregs[freg])); + return fp; +} + +static TCGv_ptr gen_fp_result_ptr(void) +{ + TCGv_ptr fp =3D tcg_temp_new_ptr(); + tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fp_result)); + return fp; +} + +static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src) +{ + TCGv t32; + TCGv_i64 t64; + + t32 =3D tcg_temp_new(); + tcg_gen_ld16u_i32(t32, src, offsetof(FPReg, l.upper)); + tcg_gen_st16_i32(t32, dest, offsetof(FPReg, l.upper)); + tcg_temp_free(t32); + + t64 =3D tcg_temp_new_i64(); + tcg_gen_ld_i64(t64, src, offsetof(FPReg, l.lower)); + tcg_gen_st_i64(t64, dest, offsetof(FPReg, l.lower)); + tcg_temp_free_i64(t64); +} + +static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr f= p) +{ + TCGv tmp; + TCGv_i64 t64; + int index =3D IS_USER(s); + + t64 =3D tcg_temp_new_i64(); + tmp =3D tcg_temp_new(); + switch (opsize) { + case OS_BYTE: + tcg_gen_qemu_ld8s(tmp, addr, index); + gen_helper_exts32(cpu_env, fp, tmp); + break; + case OS_WORD: + tcg_gen_qemu_ld16s(tmp, addr, index); + gen_helper_exts32(cpu_env, fp, tmp); + break; + case OS_LONG: + tcg_gen_qemu_ld32u(tmp, addr, index); + gen_helper_exts32(cpu_env, fp, tmp); + break; + case OS_SINGLE: + tcg_gen_qemu_ld32u(tmp, addr, index); + gen_helper_extf32(cpu_env, fp, tmp); + break; + case OS_DOUBLE: + tcg_gen_qemu_ld64(t64, addr, index); + gen_helper_extf64(cpu_env, fp, t64); + tcg_temp_free_i64(t64); + break; + case OS_EXTENDED: + if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { + gen_exception(s, s->insn_pc, EXCP_FP_UNIMP); + break; + } + tcg_gen_qemu_ld32u(tmp, addr, index); + tcg_gen_shri_i32(tmp, tmp, 16); + tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper)); + tcg_gen_addi_i32(tmp, addr, 4); + tcg_gen_qemu_ld64(t64, tmp, index); + tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower)); + break; + case OS_PACKED: + /* unimplemented data type on 68040/ColdFire + * FIXME if needed for another FPU + */ + gen_exception(s, s->insn_pc, EXCP_FP_UNIMP); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free(tmp); + tcg_temp_free_i64(t64); + gen_throws_exception =3D gen_last_qop; +} + +static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr = fp) +{ + TCGv tmp; + TCGv_i64 t64; + int index =3D IS_USER(s); + + t64 =3D tcg_temp_new_i64(); + tmp =3D tcg_temp_new(); + switch (opsize) { + case OS_BYTE: + gen_helper_reds32(tmp, cpu_env, fp); + tcg_gen_qemu_st8(tmp, addr, index); + break; + case OS_WORD: + gen_helper_reds32(tmp, cpu_env, fp); + tcg_gen_qemu_st16(tmp, addr, index); + break; + case OS_LONG: + gen_helper_reds32(tmp, cpu_env, fp); + tcg_gen_qemu_st32(tmp, addr, index); + break; + case OS_SINGLE: + gen_helper_redf32(tmp, cpu_env, fp); + tcg_gen_qemu_st32(tmp, addr, index); + break; + case OS_DOUBLE: + gen_helper_redf64(t64, cpu_env, fp); + tcg_gen_qemu_st64(t64, addr, index); + break; + case OS_EXTENDED: + if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { + gen_exception(s, s->insn_pc, EXCP_FP_UNIMP); + break; + } + tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper)); + tcg_gen_shli_i32(tmp, tmp, 16); + tcg_gen_qemu_st32(tmp, addr, index); + tcg_gen_addi_i32(tmp, addr, 4); + tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower)); + tcg_gen_qemu_st64(t64, tmp, index); + break; + case OS_PACKED: + /* unimplemented data type on 68040/ColdFire + * FIXME if needed for another FPU + */ + gen_exception(s, s->insn_pc, EXCP_FP_UNIMP); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free(tmp); + tcg_temp_free_i64(t64); + gen_throws_exception =3D gen_last_qop; +} + +static void gen_ldst_fp(DisasContext *s, int opsize, TCGv addr, + TCGv_ptr fp, ea_what what) +{ + if (what =3D=3D EA_STORE) { + gen_store_fp(s, opsize, addr, fp); + } else { + gen_load_fp(s, opsize, addr, fp); + } +} + +static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode, + int reg0, int opsize, TCGv_ptr fp, ea_what what) +{ + TCGv reg, addr, tmp; + TCGv_i64 t64; + + switch (mode) { + case 0: /* Data register direct. */ + reg =3D cpu_dregs[reg0]; + if (what =3D=3D EA_STORE) { + switch (opsize) { + case OS_BYTE: + case OS_WORD: + case OS_LONG: + gen_helper_reds32(reg, cpu_env, fp); + break; + case OS_SINGLE: + gen_helper_redf32(reg, cpu_env, fp); + break; + default: + g_assert_not_reached(); + } + } else { + tmp =3D tcg_temp_new(); + switch (opsize) { + case OS_BYTE: + tcg_gen_ext8s_i32(tmp, reg); + gen_helper_exts32(cpu_env, fp, tmp); + break; + case OS_WORD: + tcg_gen_ext16s_i32(tmp, reg); + gen_helper_exts32(cpu_env, fp, tmp); + break; + case OS_LONG: + gen_helper_exts32(cpu_env, fp, reg); + break; + case OS_SINGLE: + gen_helper_extf32(cpu_env, fp, reg); + break; + default: + g_assert_not_reached(); + } + tcg_temp_free(tmp); + } + return 0; + case 1: /* Address register direct. */ + return -1; + case 2: /* Indirect register */ + addr =3D get_areg(s, reg0); + gen_ldst_fp(s, opsize, addr, fp, what); + return 0; + case 3: /* Indirect postincrement. */ + addr =3D cpu_aregs[reg0]; + gen_ldst_fp(s, opsize, addr, fp, what); + tcg_gen_addi_i32(addr, addr, opsize_bytes(opsize)); + return 0; + case 4: /* Indirect predecrememnt. */ + addr =3D gen_lea_mode(env, s, mode, reg0, opsize); + if (IS_NULL_QREG(addr)) { + return -1; + } + gen_ldst_fp(s, opsize, addr, fp, what); + tcg_gen_mov_i32(cpu_aregs[reg0], addr); + return 0; + case 5: /* Indirect displacement. */ + case 6: /* Indirect index + displacement. */ + do_indirect: + addr =3D gen_lea_mode(env, s, mode, reg0, opsize); + if (IS_NULL_QREG(addr)) { + return -1; + } + gen_ldst_fp(s, opsize, addr, fp, what); + return 0; + case 7: /* Other */ + switch (reg0) { + case 0: /* Absolute short. */ + case 1: /* Absolute long. */ + case 2: /* pc displacement */ + case 3: /* pc index+displacement. */ + goto do_indirect; + case 4: /* Immediate. */ + if (what =3D=3D EA_STORE) { + return -1; + } + switch (opsize) { + case OS_BYTE: + tmp =3D tcg_const_i32((int8_t)read_im8(env, s)); + gen_helper_exts32(cpu_env, fp, tmp); + tcg_temp_free(tmp); + break; + case OS_WORD: + tmp =3D tcg_const_i32((int16_t)read_im16(env, s)); + gen_helper_exts32(cpu_env, fp, tmp); + tcg_temp_free(tmp); + break; + case OS_LONG: + tmp =3D tcg_const_i32(read_im32(env, s)); + gen_helper_exts32(cpu_env, fp, tmp); + tcg_temp_free(tmp); + break; + case OS_SINGLE: + tmp =3D tcg_const_i32(read_im32(env, s)); + gen_helper_extf32(cpu_env, fp, tmp); + tcg_temp_free(tmp); + break; + case OS_DOUBLE: + t64 =3D tcg_const_i64(read_im64(env, s)); + gen_helper_extf64(cpu_env, fp, t64); + tcg_temp_free_i64(t64); + break; + case OS_EXTENDED: + if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) { + gen_exception(s, s->insn_pc, EXCP_FP_UNIMP); + break; + } + tmp =3D tcg_const_i32(read_im32(env, s) >> 16); + tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper)); + tcg_temp_free(tmp); + t64 =3D tcg_const_i64(read_im64(env, s)); + tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower)); + tcg_temp_free_i64(t64); + break; + case OS_PACKED: + /* unimplemented data type on 68040/ColdFire + * FIXME if needed for another FPU + */ + gen_exception(s, s->insn_pc, EXCP_FP_UNIMP); + break; + default: + g_assert_not_reached(); + } + return 0; + default: + return -1; + } + } + return -1; +} + +static int gen_ea_fp(CPUM68KState *env, DisasContext *s, uint16_t insn, + int opsize, TCGv_ptr fp, ea_what what) +{ + int mode =3D extract32(insn, 3, 3); + int reg0 =3D REG(insn, 0); + return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what); +} + typedef struct { TCGCond tcond; bool g1; @@ -1124,42 +1432,6 @@ static void gen_lookup_tb(DisasContext *s) s->is_jmp =3D DISAS_UPDATE; } =20 -/* Generate a jump to an immediate address. */ -static void gen_jmp_im(DisasContext *s, uint32_t dest) -{ - update_cc_op(s); - tcg_gen_movi_i32(QREG_PC, dest); - s->is_jmp =3D DISAS_JUMP; -} - -/* Generate a jump to the address in qreg DEST. */ -static void gen_jmp(DisasContext *s, TCGv dest) -{ - update_cc_op(s); - tcg_gen_mov_i32(QREG_PC, dest); - s->is_jmp =3D DISAS_JUMP; -} - -static void gen_raise_exception(int nr) -{ - TCGv_i32 tmp =3D tcg_const_i32(nr); - - gen_helper_raise_exception(cpu_env, tmp); - tcg_temp_free_i32(tmp); -} - -static void gen_exception(DisasContext *s, uint32_t where, int nr) -{ - update_cc_op(s); - gen_jmp_im(s, where); - gen_raise_exception(nr); -} - -static inline void gen_addr_fault(DisasContext *s) -{ - gen_exception(s, s->insn_pc, EXCP_ADDRESS); -} - #define SRC_EA(env, result, opsize, op_sign, addrp) do { \ result =3D gen_ea(env, s, insn, opsize, NULL_QREG, addrp, \ op_sign ? EA_LOADS : EA_LOADU); \ @@ -4133,15 +4405,11 @@ undef: DISAS_INSN(fpu) { uint16_t ext; - int32_t offset; int opmode; - TCGv_i64 src; - TCGv_i64 dest; - TCGv_i64 res; TCGv tmp32; int round; - int set_dest; int opsize; + TCGv_ptr cpu_src, cpu_dest; =20 ext =3D read_im16(env, s); opmode =3D ext & 0x7f; @@ -4151,59 +4419,12 @@ DISAS_INSN(fpu) case 1: goto undef; case 3: /* fmove out */ - src =3D FREG(ext, 7); - tmp32 =3D tcg_temp_new_i32(); - /* fmove */ - /* ??? TODO: Proper behavior on overflow. */ - + cpu_src =3D gen_fp_ptr(REG(ext, 7)); opsize =3D ext_opsize(ext, 10); - switch (opsize) { - case OS_LONG: - gen_helper_f64_to_i32(tmp32, cpu_env, src); - break; - case OS_SINGLE: - gen_helper_f64_to_f32(tmp32, cpu_env, src); - break; - case OS_WORD: - gen_helper_f64_to_i32(tmp32, cpu_env, src); - break; - case OS_DOUBLE: - tcg_gen_mov_i32(tmp32, AREG(insn, 0)); - switch ((insn >> 3) & 7) { - case 2: - case 3: - break; - case 4: - tcg_gen_addi_i32(tmp32, tmp32, -8); - break; - case 5: - offset =3D cpu_ldsw_code(env, s->pc); - s->pc +=3D 2; - tcg_gen_addi_i32(tmp32, tmp32, offset); - break; - default: - goto undef; - } - gen_store64(s, tmp32, src); - switch ((insn >> 3) & 7) { - case 3: - tcg_gen_addi_i32(tmp32, tmp32, 8); - tcg_gen_mov_i32(AREG(insn, 0), tmp32); - break; - case 4: - tcg_gen_mov_i32(AREG(insn, 0), tmp32); - break; - } - tcg_temp_free_i32(tmp32); - return; - case OS_BYTE: - gen_helper_f64_to_i32(tmp32, cpu_env, src); - break; - default: - goto undef; + if (gen_ea_fp(env, s, insn, opsize, cpu_src, EA_STORE) =3D=3D -1) { + gen_addr_fault(s); } - DEST_EA(env, insn, opsize, tmp32, NULL); - tcg_temp_free_i32(tmp32); + tcg_temp_free_ptr(cpu_src); return; case 4: /* fmove to control register. */ case 5: /* fmove from control register. */ @@ -4213,6 +4434,7 @@ DISAS_INSN(fpu) case 7: { TCGv addr; + TCGv_ptr fp; uint16_t mask; int i; if ((ext & 0x1f00) !=3D 0x1000 || (ext & 0xff) =3D=3D 0) @@ -4225,136 +4447,86 @@ DISAS_INSN(fpu) addr =3D tcg_temp_new_i32(); tcg_gen_mov_i32(addr, tmp32); mask =3D 0x80; + fp =3D tcg_temp_new_ptr(); for (i =3D 0; i < 8; i++) { if (ext & mask) { - dest =3D FREG(i, 0); - if (ext & (1 << 13)) { - /* store */ - tcg_gen_qemu_stf64(dest, addr, IS_USER(s)); - } else { - /* load */ - tcg_gen_qemu_ldf64(dest, addr, IS_USER(s)); - } + tcg_gen_addi_ptr(fp, cpu_env, + offsetof(CPUM68KState, fregs[i])); + gen_ldst_fp(s, OS_DOUBLE, addr, fp, + (ext & (1 << 13)) ? EA_STORE : EA_LOADS); if (ext & (mask - 1)) tcg_gen_addi_i32(addr, addr, 8); } mask >>=3D 1; } tcg_temp_free_i32(addr); + tcg_temp_free_ptr(fp); } return; } if (ext & (1 << 14)) { /* Source effective address. */ opsize =3D ext_opsize(ext, 10); - if (opsize =3D=3D OS_DOUBLE) { - tmp32 =3D tcg_temp_new_i32(); - tcg_gen_mov_i32(tmp32, AREG(insn, 0)); - switch ((insn >> 3) & 7) { - case 2: - case 3: - break; - case 4: - tcg_gen_addi_i32(tmp32, tmp32, -8); - break; - case 5: - offset =3D cpu_ldsw_code(env, s->pc); - s->pc +=3D 2; - tcg_gen_addi_i32(tmp32, tmp32, offset); - break; - case 7: - offset =3D cpu_ldsw_code(env, s->pc); - offset +=3D s->pc - 2; - s->pc +=3D 2; - tcg_gen_addi_i32(tmp32, tmp32, offset); - break; - default: - goto undef; - } - src =3D gen_load64(s, tmp32); - switch ((insn >> 3) & 7) { - case 3: - tcg_gen_addi_i32(tmp32, tmp32, 8); - tcg_gen_mov_i32(AREG(insn, 0), tmp32); - break; - case 4: - tcg_gen_mov_i32(AREG(insn, 0), tmp32); - break; - } - tcg_temp_free_i32(tmp32); - } else { - SRC_EA(env, tmp32, opsize, 1, NULL); - src =3D tcg_temp_new_i64(); - switch (opsize) { - case OS_LONG: - case OS_WORD: - case OS_BYTE: - gen_helper_i32_to_f64(src, cpu_env, tmp32); - break; - case OS_SINGLE: - gen_helper_f32_to_f64(src, cpu_env, tmp32); - break; - } + cpu_src =3D gen_fp_result_ptr(); + if (gen_ea_fp(env, s, insn, opsize, cpu_src, EA_LOADS) =3D=3D -1) { + gen_addr_fault(s); + return; } } else { /* Source register. */ - src =3D FREG(ext, 10); + opsize =3D OS_EXTENDED; + cpu_src =3D gen_fp_ptr(REG(ext, 10)); } - dest =3D FREG(ext, 7); - res =3D tcg_temp_new_i64(); - if (opmode !=3D 0x3a) - tcg_gen_mov_f64(res, dest); round =3D 1; - set_dest =3D 1; + cpu_dest =3D gen_fp_ptr(REG(ext, 7)); switch (opmode) { case 0: case 0x40: case 0x44: /* fmove */ - tcg_gen_mov_f64(res, src); + gen_fp_move(cpu_dest, cpu_src); break; case 1: /* fint */ - gen_helper_iround_f64(res, cpu_env, src); + gen_helper_firound(cpu_env, cpu_dest, cpu_src); round =3D 0; break; case 3: /* fintrz */ - gen_helper_itrunc_f64(res, cpu_env, src); + gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src); round =3D 0; break; case 4: case 0x41: case 0x45: /* fsqrt */ - gen_helper_sqrt_f64(res, cpu_env, src); + gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src); break; case 0x18: case 0x58: case 0x5c: /* fabs */ - gen_helper_abs_f64(res, src); + gen_helper_fabs(cpu_env, cpu_dest, cpu_src); break; case 0x1a: case 0x5a: case 0x5e: /* fneg */ - gen_helper_chs_f64(res, src); + gen_helper_fchs(cpu_env, cpu_dest, cpu_src); break; case 0x20: case 0x60: case 0x64: /* fdiv */ - gen_helper_div_f64(res, cpu_env, res, src); + gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest); break; case 0x22: case 0x62: case 0x66: /* fadd */ - gen_helper_add_f64(res, cpu_env, res, src); + gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest); break; case 0x23: case 0x63: case 0x67: /* fmul */ - gen_helper_mul_f64(res, cpu_env, res, src); + gen_helper_fmul(cpu_env, cpu_dest, cpu_src, cpu_dest); break; case 0x28: case 0x68: case 0x6c: /* fsub */ - gen_helper_sub_f64(res, cpu_env, res, src); + gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest); break; case 0x38: /* fcmp */ - gen_helper_sub_cmp_f64(res, cpu_env, res, src); - set_dest =3D 0; + tcg_temp_free_ptr(cpu_dest); + cpu_dest =3D gen_fp_result_ptr(); + gen_helper_fsub_cmp(cpu_env, cpu_dest, cpu_src, cpu_dest); round =3D 0; break; case 0x3a: /* ftst */ - tcg_gen_mov_f64(res, src); - set_dest =3D 0; + tcg_temp_free_ptr(cpu_dest); + cpu_dest =3D gen_fp_result_ptr(); + gen_fp_move(cpu_dest, cpu_src); round =3D 0; break; default: goto undef; } - if (ext & (1 << 14)) { - tcg_temp_free_i64(src); - } if (round) { if (opmode & 0x40) { if ((opmode & 0x4) !=3D 0) @@ -4364,16 +4536,18 @@ DISAS_INSN(fpu) } } if (round) { - TCGv tmp =3D tcg_temp_new_i32(); - gen_helper_f64_to_f32(tmp, cpu_env, res); - gen_helper_f32_to_f64(res, cpu_env, tmp); - tcg_temp_free_i32(tmp); - } - tcg_gen_mov_f64(QREG_FP_RESULT, res); - if (set_dest) { - tcg_gen_mov_f64(dest, res); + TCGv tmp =3D tcg_temp_new(); + gen_helper_redf32(tmp, cpu_env, cpu_dest); + gen_helper_extf32(cpu_env, cpu_dest, tmp); + tcg_temp_free(tmp); + } else { + TCGv_i64 t64 =3D tcg_temp_new_i64(); + gen_helper_redf64(t64, cpu_env, cpu_dest); + gen_helper_extf64(cpu_env, cpu_dest, t64); + tcg_temp_free_i64(t64); } - tcg_temp_free_i64(res); + tcg_temp_free_ptr(cpu_src); + tcg_temp_free_ptr(cpu_dest); return; undef: /* FIXME: Is this right for offset addressing modes? */ @@ -4387,6 +4561,7 @@ DISAS_INSN(fbcc) uint32_t addr; TCGv flag; TCGLabel *l1; + TCGv_ptr fp_result; =20 addr =3D s->pc; offset =3D cpu_ldsw_code(env, s->pc); @@ -4398,7 +4573,9 @@ DISAS_INSN(fbcc) l1 =3D gen_new_label(); /* TODO: Raise BSUN exception. */ flag =3D tcg_temp_new(); - gen_helper_compare_f64(flag, cpu_env, QREG_FP_RESULT); + fp_result =3D gen_fp_result_ptr(); + gen_helper_fcompare(flag, cpu_env, fp_result); + tcg_temp_free_ptr(fp_result); /* Jump to l1 if condition is true. */ switch (insn & 0xf) { case 0: /* f */ @@ -5028,11 +5205,15 @@ void register_m68k_insns (CPUM68KState *env) INSN(bfop_reg, eec0, fff8, BITFIELD); /* bfset */ INSN(bfop_mem, e8c0, ffc0, BITFIELD); /* bftst */ INSN(bfop_reg, e8c0, fff8, BITFIELD); /* bftst */ - INSN(undef_fpu, f000, f000, CF_ISA_A); + BASE(undef_fpu, f000, f000); INSN(fpu, f200, ffc0, CF_FPU); INSN(fbcc, f280, ffc0, CF_FPU); INSN(frestore, f340, ffc0, CF_FPU); - INSN(fsave, f340, ffc0, CF_FPU); + INSN(fsave, f300, ffc0, CF_FPU); + INSN(fpu, f200, ffc0, FPU); + INSN(fbcc, f280, ff80, FPU); + INSN(frestore, f340, ffc0, FPU); + INSN(fsave, f300, ffc0, FPU); INSN(intouch, f340, ffc0, CF_ISA_A); INSN(cpushl, f428, ff38, CF_ISA_A); INSN(wddata, fb00, ff00, CF_ISA_A); @@ -5158,6 +5339,18 @@ void gen_intermediate_code(CPUM68KState *env, Transl= ationBlock *tb) tb->icount =3D num_insns; } =20 +static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_= t low) +{ + floatx80 a =3D { .high =3D high, .low =3D low }; + union { + float64 f64; + double d; + } u; + + u.f64 =3D floatx80_to_float64(a, &env->fp_status); + return u.d; +} + void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprin= tf, int flags) { @@ -5165,20 +5358,19 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fpr= intf_function cpu_fprintf, CPUM68KState *env =3D &cpu->env; int i; uint16_t sr; - CPU_DoubleU u; - for (i =3D 0; i < 8; i++) - { - u.d =3D env->fregs[i]; - cpu_fprintf(f, "D%d =3D %08x A%d =3D %08x F%d =3D %08x%08x (%1= 2g)\n", + for (i =3D 0; i < 8; i++) { + cpu_fprintf(f, "D%d =3D %08x A%d =3D %08x " + "F%d =3D %04x %016"PRIx64" (%12g)\n", i, env->dregs[i], i, env->aregs[i], - i, u.l.upper, u.l.lower, *(double *)&u.d); - } + i, env->fregs[i].l.upper, env->fregs[i].l.lower, + floatx80_to_double(env, env->fregs[i].l.upper, + env->fregs[i].l.lower)); + } cpu_fprintf (f, "PC =3D %08x ", env->pc); sr =3D env->sr | cpu_m68k_get_ccr(env); cpu_fprintf(f, "SR =3D %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-'); - cpu_fprintf (f, "FPRESULT =3D %12g\n", *(double *)&env->fp_result); } =20 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, --=20 2.9.4 From nobody Sat May 4 15:20:10 2024 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.zoho.com; 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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497992037857830.7663036116003; Tue, 20 Jun 2017 13:53:57 -0700 (PDT) Received: from localhost ([::1]:50613 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ9r-0001PB-EH for importer@patchew.org; Tue, 20 Jun 2017 16:53:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55352) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ81-0008AK-Qk for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dNQ80-0004EG-1h for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:01 -0400 Received: from mout.kundenserver.de ([217.72.192.75]:55301) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dNQ7z-0004DN-Lw for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:51:59 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0M7sMi-1djMmW3oLA-00vPGP; Tue, 20 Jun 2017 22:51:29 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Tue, 20 Jun 2017 22:51:19 +0200 Message-Id: <20170620205121.26515-5-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170620205121.26515-1-laurent@vivier.eu> References: <20170620205121.26515-1-laurent@vivier.eu> X-Provags-ID: V03:K0:yB5c3kAqPXb9cmnT26FoZRA6EqtYCnnzwTtj6z7zn42GJmJIBZQ NaUrUInO/glUsCXZTkR+FD/T6AKb2hb6AiwsUGcksL1qjkMRk7anWem0uLD9L34mxw1dWlV 3i3iuBuIT/Q/Q1ej0GLOipfSORevnVBdP4rV16Xg1ZvVOf46XTtyoq3uRwPcTTZL+Z11FnV U6KTCOiZk0Qi6OxwEdT0g== X-UI-Out-Filterresults: notjunk:1;V01:K0:93jVBLM+ipg=:ilLfF1fXTtF7rXiIeRdhIL 8olDlcmPFuvK6pxx3TdYVwXz2obKb+ptH2SU7knCvBwAviVMfYEkD/W+W0EJJNBJQzi4ZK9Z9 qz2EqxZSg73AMHGVgNHI6+6YGAN+AszjPkvNMX65Y42Y1Jq/5owvtt9YTkznMq/PaNUt/9CgD NXMvReq0L0eCIwcqKkCO0nJKj/xojw4N62mMTXeCMiGqRqYDm0Aw2HhHkB4f+Qmt7nnOn5HQl dM95AMH4/H9l3DkwXWnLoMGuNRndTi4pwW0riqH59SGJfrNQJP5kRQ3CWqhz7CYCIgEyABPOL +lBEv2sabR3xLkFy4MzfTCsPRsPDzBQKZJotN+4Xt+0d86kjCjfZeiDroAuikNYhkDeE0xkQp erGhAcdp+GUwvhGWcN5Vp6MrnIUU19EI5hRK3ppwzJQpiSRO/PzvK3uzvBWDWsUoEthNl+gaB RKndw5AmlUdWGBQE5VCectrQn2TSPbV1TZ7nff2AgowazNT/lw92k05M0dqr9OtbtYOXwOfS3 iawwQFTxBOrlbzTtpCnZheva0Cqmr9cJ/dPU+X3SI2PR8IiNBvty+phQPQyiaIlnfYmkPatLt h6Ln+i2AiJikh92IQwe3A8C0aQ6Sc+Pt+rbhYx1Ct0z/s9UpbuGIfH5B3EGjxE6lxAF3jatDs sobVJem2TSm83y6r7dOfI23gdKDJ7j2VjIg9oU9p1miSlTbe7uq61RUTBPNY6bXHDvuU= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.75 Subject: [Qemu-devel] [PATCH v5 4/6] target-m68k: define 96bit FP registers for gdb on 680x0 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: Thomas Huth , Riku Voipio , Laurent Vivier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson --- configure | 2 +- gdb-xml/m68k-fp.xml | 21 +++++++++++++++++++++ target/m68k/helper.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 gdb-xml/m68k-fp.xml diff --git a/configure b/configure index db0798d..4df871c 100755 --- a/configure +++ b/configure @@ -6066,7 +6066,7 @@ case "$target_name" in ;; m68k) bflt=3D"yes" - gdb_xml_files=3D"cf-core.xml cf-fp.xml" + gdb_xml_files=3D"cf-core.xml cf-fp.xml m68k-fp.xml" ;; microblaze|microblazeel) TARGET_ARCH=3Dmicroblaze diff --git a/gdb-xml/m68k-fp.xml b/gdb-xml/m68k-fp.xml new file mode 100644 index 0000000..64290d1 --- /dev/null +++ b/gdb-xml/m68k-fp.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + , + + diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 8bfc881..f2de6b5 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -102,6 +102,48 @@ static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8= _t *mem_buf, int n) return 0; } =20 +static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n) +{ + if (n < 8) { + stw_be_p(mem_buf, env->fregs[n].l.upper); + memset(mem_buf + 2, 0, 2); + stq_be_p(mem_buf + 4, env->fregs[n].l.lower); + return 12; + } + switch (n) { + case 8: /* fpcontrol */ + stl_be_p(mem_buf, env->fpcr); + return 4; + case 9: /* fpstatus */ + stl_be_p(mem_buf, env->fpsr); + return 4; + case 10: /* fpiar, not implemented */ + memset(mem_buf, 0, 4); + return 4; + } + return 0; +} + +static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n) +{ + if (n < 8) { + env->fregs[n].l.upper =3D lduw_be_p(mem_buf); + env->fregs[n].l.lower =3D ldq_be_p(mem_buf + 4); + return 12; + } + switch (n) { + case 8: /* fpcontrol */ + env->fpcr =3D ldl_p(mem_buf); + return 4; + case 9: /* fpstatus */ + env->fpsr =3D ldl_p(mem_buf); + return 4; + case 10: /* fpiar, not implemented */ + return 4; + } + return 0; +} + M68kCPU *cpu_m68k_init(const char *cpu_model) { M68kCPU *cpu; @@ -130,6 +172,9 @@ void m68k_cpu_init_gdb(M68kCPU *cpu) if (m68k_feature(env, M68K_FEATURE_CF_FPU)) { gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_re= g, 11, "cf-fp.xml", 18); + } else if (m68k_feature(env, M68K_FEATURE_FPU)) { + gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg, + m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", = 18); } /* TODO: Add [E]MAC registers. */ } --=20 2.9.4 From nobody Sat May 4 15:20:10 2024 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.zoho.com; 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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497992169385444.8841721780889; Tue, 20 Jun 2017 13:56:09 -0700 (PDT) Received: from localhost ([::1]:50627 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQBz-00036j-Uk for importer@patchew.org; Tue, 20 Jun 2017 16:56:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55493) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ8J-0008Qd-Ib for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dNQ8E-0004LM-T3 for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:19 -0400 Received: from mout.kundenserver.de ([217.72.192.74]:59953) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dNQ8E-0004L5-Dj for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:14 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0MbPlM-1d6zhN3BoK-00ImeX; Tue, 20 Jun 2017 22:51:30 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Tue, 20 Jun 2017 22:51:20 +0200 Message-Id: <20170620205121.26515-6-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170620205121.26515-1-laurent@vivier.eu> References: <20170620205121.26515-1-laurent@vivier.eu> X-Provags-ID: V03:K0:3GgZIvoHSneK/rPVcUTszuEsGVFTVjkS2hIv9SjXVVMEOxBl2Md b7n4IRjtZqPudoU22Hw8yAWvw0j6lGjUuE+4rJanRpC3Bdd/Ao5pJ19s334Gisy0ZX6ZZfd eVVGEAhmytN5oLIhyD6tw5a6TkilnHycbnW3gf59JVCfk4pUjm7dRYgfRAHKiF4qrTlCKB4 5w6qrL1hlZM1PyYGGwb3g== X-UI-Out-Filterresults: notjunk:1;V01:K0:iWXn0mKZVc0=:hjxAajOd9VKgJEvbIIcy9r 6NSYFCs43vIb+hHOL1kt41nMeOg14oJq8dhjPedtslHUQ+0Z58QaKqdHNvvZKlSnPqzrrCuS9 461xsYS6INY7ASvvESjvF4zoibmAEqHla0sk6/aIS244vzp3ThFXGcEPsuBAv0HRt3Evtx137 5icoEIpI9aZacraGI3+sGsn0RSwjNq/+0vIUqrqvaYUitAos1oVjzSWW4cAJZmCcs0Weeg4N6 t+SCcYG5cMC8u1dvRhszA8wHZwrIsTIsSwkWlRW1KnOMPp/aLJrxg/HuBV2s5FEuqnbUKlxOq Mrad63uvQQ0yUqDv2PR5WxlNpPAavJOo8BdfmnGL+pCKDqodXA7Qhij9rUoSvje3L1MqBHH22 NUh2SR7T2/vvMiQH94kxFswGKyiWrK6GYG31hnGDAjFs/HdDrcfiys6msNL5nTrwrZpPn2VLA 1TyyJmRwYjj6wWEDuWErc4DjSWN8k/dTfuf/sDd4KyVkfEzOYI3wi5Wyswnl7GG6QhYOQNHD5 HqPvdiF3AN4knvCRIzkgMJQl6fp2k4e9iEolAv+eSvjy3KxcqId04ScU0cPboclBCnQl15Zb0 YdwbISo7aXMYB/w+w+zbW8y5YhuhzrIKBLW4TbYxE7btFGJ2qe61bDtiiTrRwAdMb2A8cKBhs zSMDUDrxHLG4OguIs4jx+t9qTU83M8DjL026YjZ/OPvL2ntS71BKCVxPmksvALQYo2FM= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.74 Subject: [Qemu-devel] [PATCH v5 5/6] target-m68k: add FPCR and FPSR 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: Thomas Huth , Riku Voipio , Laurent Vivier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson --- target/m68k/cpu.c | 2 +- target/m68k/cpu.h | 43 +++++- target/m68k/fpu_helper.c | 117 +++++++++++++--- target/m68k/helper.c | 22 ++- target/m68k/helper.h | 5 +- target/m68k/translate.c | 351 +++++++++++++++++++++++++++++++++++--------= ---- 6 files changed, 421 insertions(+), 119 deletions(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 435456f..a14b6dd 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -62,7 +62,7 @@ static void m68k_cpu_reset(CPUState *s) for (i =3D 0; i < 8; i++) { env->fregs[i].d =3D nan; } - env->fpcr =3D 0; + cpu_m68k_set_fpcr(env, 0); env->fpsr =3D 0; =20 cpu_m68k_set_ccr(env, 0); diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index beb8ebc..38a7e11 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -171,6 +171,7 @@ int cpu_m68k_signal_handler(int host_signum, void *pinf= o, void *puc); uint32_t cpu_m68k_get_ccr(CPUM68KState *env); void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t); +void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val); =20 =20 /* Instead of computing the condition codes after each m68k instruction, @@ -215,6 +216,43 @@ typedef enum { #define M68K_SSP 0 #define M68K_USP 1 =20 +#define M68K_FPIAR_SHIFT 0 +#define M68K_FPIAR (1 << M68K_FPIAR_SHIFT) +#define M68K_FPSR_SHIFT 1 +#define M68K_FPSR (1 << M68K_FPSR_SHIFT) +#define M68K_FPCR_SHIFT 2 +#define M68K_FPCR (1 << M68K_FPCR_SHIFT) + +/* Floating-Point Status Register */ + +/* Condition Code */ +#define FPSR_CC_MASK 0x0f000000 +#define FPSR_CC_A 0x01000000 /* Not-A-Number */ +#define FPSR_CC_I 0x02000000 /* Infinity */ +#define FPSR_CC_Z 0x04000000 /* Zero */ +#define FPSR_CC_N 0x08000000 /* Negative */ + +/* Quotient */ + +#define FPSR_QT_MASK 0x00ff0000 + +/* Floating-Point Control Register */ +/* Rounding mode */ +#define FPCR_RND_MASK 0x0030 +#define FPCR_RND_N 0x0000 +#define FPCR_RND_Z 0x0010 +#define FPCR_RND_M 0x0020 +#define FPCR_RND_P 0x0030 + +/* Rounding precision */ +#define FPCR_PREC_MASK 0x00c0 +#define FPCR_PREC_X 0x0000 +#define FPCR_PREC_S 0x0040 +#define FPCR_PREC_D 0x0080 +#define FPCR_PREC_U 0x00c0 + +#define FPCR_EXCP_MASK 0xff00 + /* CACR fields are implementation defined, but some bits are common. */ #define M68K_CACR_EUSP 0x10 =20 @@ -231,8 +269,6 @@ typedef enum { void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector); void m68k_switch_sp(CPUM68KState *env); =20 -#define M68K_FPCR_PREC (1 << 6) - void do_m68k_semihosting(CPUM68KState *env, int nr); =20 /* There are 4 ColdFire core ISA revisions: A, A+, B and C. @@ -310,8 +346,7 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *e= nv, target_ulong *pc, { *pc =3D env->pc; *cs_base =3D 0; - *flags =3D (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ - | (env->sr & SR_S) /* Bit 13 */ + *flags =3D (env->sr & SR_S) /* Bit 13 */ | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */ } =20 diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index f4d3821..a9e17f5 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -58,9 +58,74 @@ void HELPER(firound)(CPUM68KState *env, FPReg *res, FPRe= g *val) res->d =3D floatx80_round_to_int(val->d, &env->fp_status); } =20 +static void m68k_restore_precision_mode(CPUM68KState *env) +{ + switch (env->fpcr & FPCR_PREC_MASK) { + case FPCR_PREC_X: /* extended */ + set_floatx80_rounding_precision(80, &env->fp_status); + break; + case FPCR_PREC_S: /* single */ + set_floatx80_rounding_precision(32, &env->fp_status); + break; + case FPCR_PREC_D: /* double */ + set_floatx80_rounding_precision(64, &env->fp_status); + break; + case FPCR_PREC_U: /* undefined */ + default: + break; + } +} + +static void cf_restore_precision_mode(CPUM68KState *env) +{ + if (env->fpcr & FPCR_PREC_S) { /* single */ + set_floatx80_rounding_precision(32, &env->fp_status); + } else { /* double */ + set_floatx80_rounding_precision(64, &env->fp_status); + } +} + +static void restore_rounding_mode(CPUM68KState *env) +{ + switch (env->fpcr & FPCR_RND_MASK) { + case FPCR_RND_N: /* round to nearest */ + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + break; + case FPCR_RND_Z: /* round to zero */ + set_float_rounding_mode(float_round_to_zero, &env->fp_status); + break; + case FPCR_RND_M: /* round toward minus infinity */ + set_float_rounding_mode(float_round_down, &env->fp_status); + break; + case FPCR_RND_P: /* round toward positive infinity */ + set_float_rounding_mode(float_round_up, &env->fp_status); + break; + } +} + +void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val) +{ + env->fpcr =3D val & 0xffff; + + if (m68k_feature(env, M68K_FEATURE_CF_FPU)) { + cf_restore_precision_mode(env); + } else { + m68k_restore_precision_mode(env); + } + restore_rounding_mode(env); +} + void HELPER(fitrunc)(CPUM68KState *env, FPReg *res, FPReg *val) { + int rounding_mode =3D get_float_rounding_mode(&env->fp_status); + set_float_rounding_mode(float_round_to_zero, &env->fp_status); res->d =3D floatx80_round_to_int(val->d, &env->fp_status); + set_float_rounding_mode(rounding_mode, &env->fp_status); +} + +void HELPER(set_fpcr)(CPUM68KState *env, uint32_t val) +{ + cpu_m68k_set_fpcr(env, val); } =20 void HELPER(fsqrt)(CPUM68KState *env, FPReg *res, FPReg *val) @@ -98,24 +163,44 @@ void HELPER(fdiv)(CPUM68KState *env, FPReg *res, FPReg= *val0, FPReg *val1) res->d =3D floatx80_div(val1->d, val0->d, &env->fp_status); } =20 -void HELPER(fsub_cmp)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *v= al1) -{ - /* ??? This may incorrectly raise exceptions. */ - /* ??? Should flush denormals to zero. */ - res->d =3D floatx80_sub(val0->d, val1->d, &env->fp_status); - if (floatx80_is_quiet_nan(res->d, &env->fp_status)) { - /* +/-inf compares equal against itself, but sub returns nan. */ - if (!floatx80_is_quiet_nan(val0->d, &env->fp_status) - && !floatx80_is_quiet_nan(val1->d, &env->fp_status)) { - res->d =3D floatx80_zero; - if (floatx80_lt_quiet(val0->d, res->d, &env->fp_status)) { - res->d =3D floatx80_chs(res->d); - } - } +static int float_comp_to_cc(int float_compare) +{ + switch (float_compare) { + case float_relation_equal: + return FPSR_CC_Z; + case float_relation_less: + return FPSR_CC_N; + case float_relation_unordered: + return FPSR_CC_A; + case float_relation_greater: + return 0; + default: + g_assert_not_reached(); } } =20 -uint32_t HELPER(fcompare)(CPUM68KState *env, FPReg *val) +void HELPER(fcmp)(CPUM68KState *env, FPReg *val0, FPReg *val1) { - return floatx80_compare_quiet(val->d, floatx80_zero, &env->fp_status); + int float_compare; + + float_compare =3D floatx80_compare(val1->d, val0->d, &env->fp_status); + env->fpsr =3D (env->fpsr & ~FPSR_CC_MASK) | float_comp_to_cc(float_com= pare); +} + +void HELPER(ftst)(CPUM68KState *env, FPReg *val) +{ + uint32_t cc =3D 0; + + if (floatx80_is_neg(val->d)) { + cc |=3D FPSR_CC_N; + } + + if (floatx80_is_any_nan(val->d)) { + cc |=3D FPSR_CC_A; + } else if (floatx80_is_infinity(val->d)) { + cc |=3D FPSR_CC_I; + } else if (floatx80_is_zero(val->d)) { + cc |=3D FPSR_CC_Z; + } + env->fpsr =3D (env->fpsr & ~FPSR_CC_MASK) | cc; } diff --git a/target/m68k/helper.c b/target/m68k/helper.c index f2de6b5..caae291 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -80,8 +80,14 @@ static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t= *mem_buf, int n) stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s)); return 8; } - if (n < 11) { - /* FP control registers (not implemented) */ + switch (n) { + case 8: /* fpcontrol */ + stl_be_p(mem_buf, env->fpcr); + return 4; + case 9: /* fpstatus */ + stl_be_p(mem_buf, env->fpsr); + return 4; + case 10: /* fpiar, not implemented */ memset(mem_buf, 0, 4); return 4; } @@ -95,8 +101,14 @@ static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_= t *mem_buf, int n) env->fregs[n].d =3D float64_to_floatx80(ldfq_p(mem_buf), &s); return 8; } - if (n < 11) { - /* FP control registers (not implemented) */ + switch (n) { + case 8: /* fpcontrol */ + cpu_m68k_set_fpcr(env, ldl_p(mem_buf)); + return 4; + case 9: /* fpstatus */ + env->fpsr =3D ldl_p(mem_buf); + return 4; + case 10: /* fpiar, not implemented */ return 4; } return 0; @@ -133,7 +145,7 @@ static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint= 8_t *mem_buf, int n) } switch (n) { case 8: /* fpcontrol */ - env->fpcr =3D ldl_p(mem_buf); + cpu_m68k_set_fpcr(env, ldl_p(mem_buf)); return 4; case 9: /* fpstatus */ env->fpsr =3D ldl_p(mem_buf); diff --git a/target/m68k/helper.h b/target/m68k/helper.h index d871be6..98cbf18 100644 --- a/target/m68k/helper.h +++ b/target/m68k/helper.h @@ -32,8 +32,9 @@ DEF_HELPER_4(fadd, void, env, fp, fp, fp) DEF_HELPER_4(fsub, void, env, fp, fp, fp) DEF_HELPER_4(fmul, void, env, fp, fp, fp) DEF_HELPER_4(fdiv, void, env, fp, fp, fp) -DEF_HELPER_4(fsub_cmp, void, env, fp, fp, fp) -DEF_HELPER_2(fcompare, i32, env, fp) +DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp) +DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32) +DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp) =20 DEF_HELPER_3(mac_move, void, env, i32, i32) DEF_HELPER_3(macmulf, i64, env, i32, i32) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 73f691f..7aa0fdc 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -120,7 +120,6 @@ typedef struct DisasContext { CCOp cc_op; /* Current CC operation */ int cc_op_synced; int user; - uint32_t fpcr; struct TranslationBlock *tb; int singlestep_enabled; TCGv_i64 mactmp; @@ -4371,33 +4370,139 @@ DISAS_INSN(trap) gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf)); } =20 +static void gen_load_fcr(DisasContext *s, TCGv res, int reg) +{ + switch (reg) { + case M68K_FPIAR: + tcg_gen_movi_i32(res, 0); + break; + case M68K_FPSR: + tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpsr)); + break; + case M68K_FPCR: + tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpcr)); + break; + } +} + +static void gen_store_fcr(DisasContext *s, TCGv val, int reg) +{ + switch (reg) { + case M68K_FPIAR: + break; + case M68K_FPSR: + tcg_gen_st_i32(val, cpu_env, offsetof(CPUM68KState, fpsr)); + break; + case M68K_FPCR: + gen_helper_set_fpcr(cpu_env, val); + break; + } +} + +static void gen_qemu_store_fcr(DisasContext *s, TCGv addr, int reg) +{ + int index =3D IS_USER(s); + TCGv tmp; + + tmp =3D tcg_temp_new(); + gen_load_fcr(s, tmp, reg); + tcg_gen_qemu_st32(tmp, addr, index); + tcg_temp_free(tmp); +} + +static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg) +{ + int index =3D IS_USER(s); + TCGv tmp; + + tmp =3D tcg_temp_new(); + tcg_gen_qemu_ld32u(tmp, addr, index); + gen_store_fcr(s, tmp, reg); + tcg_temp_free(tmp); +} + + static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s, uint32_t insn, uint32_t ext) { int mask =3D (ext >> 10) & 7; int is_write =3D (ext >> 13) & 1; - TCGv val; + int mode =3D extract32(insn, 3, 3); + int i; + TCGv addr, tmp; =20 - switch (mask) { - case 1: /* FPIAR */ - case 2: /* FPSR */ - default: - qemu_log_mask(LOG_UNIMP, "Unimplemented: fmove to/from control %d", - mask); - goto undef; - case 4: /* FPCR */ + switch (mode) { + case 0: /* Dn */ + if (mask !=3D M68K_FPIAR && mask !=3D M68K_FPSR && mask !=3D M68K_= FPCR) { + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } if (is_write) { - val =3D tcg_const_i32(0); - DEST_EA(env, insn, OS_LONG, val, NULL); - tcg_temp_free(val); + gen_load_fcr(s, DREG(insn, 0), mask); + } else { + gen_store_fcr(s, DREG(insn, 0), mask); } - /* Not implemented. Ignore register update */ + return; + case 1: /* An, only with FPIAR */ + if (mask !=3D M68K_FPIAR) { + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + if (is_write) { + gen_load_fcr(s, AREG(insn, 0), mask); + } else { + gen_store_fcr(s, AREG(insn, 0), mask); + } + return; + default: break; } - return; -undef: - s->pc -=3D 2; - disas_undef_fpu(env, s, insn); + + tmp =3D gen_lea(env, s, insn, OS_LONG); + if (IS_NULL_QREG(tmp)) { + gen_addr_fault(s); + return; + } + + addr =3D tcg_temp_new(); + tcg_gen_mov_i32(addr, tmp); + + /* mask: + * + * 0b100 Floating-Point Control Register + * 0b010 Floating-Point Status Register + * 0b001 Floating-Point Instruction Address Register + * + */ + + if (is_write && mode =3D=3D 4) { + for (i =3D 2; i >=3D 0; i--, mask >>=3D 1) { + if (mask & 1) { + gen_qemu_store_fcr(s, addr, 1 << i); + if (mask !=3D 1) { + tcg_gen_subi_i32(addr, addr, opsize_bytes(OS_LONG)); + } + } + } + tcg_gen_mov_i32(AREG(insn, 0), addr); + } else { + for (i =3D 0; i < 3; i++, mask >>=3D 1) { + if (mask & 1) { + if (is_write) { + gen_qemu_store_fcr(s, addr, 1 << i); + } else { + gen_qemu_load_fcr(s, addr, 1 << i); + } + if (mask !=3D 1 || mode =3D=3D 3) { + tcg_gen_addi_i32(addr, addr, opsize_bytes(OS_LONG)); + } + } + } + if (mode =3D=3D 3) { + tcg_gen_mov_i32(AREG(insn, 0), addr); + } + } + tcg_temp_free_i32(addr); } =20 /* ??? FP exceptions are not implemented. Most exceptions are deferred un= til @@ -4407,7 +4512,6 @@ DISAS_INSN(fpu) uint16_t ext; int opmode; TCGv tmp32; - int round; int opsize; TCGv_ptr cpu_src, cpu_dest; =20 @@ -4424,6 +4528,7 @@ DISAS_INSN(fpu) if (gen_ea_fp(env, s, insn, opsize, cpu_src, EA_STORE) =3D=3D -1) { gen_addr_fault(s); } + gen_helper_ftst(cpu_env, cpu_src); tcg_temp_free_ptr(cpu_src); return; case 4: /* fmove to control register. */ @@ -4477,7 +4582,6 @@ DISAS_INSN(fpu) opsize =3D OS_EXTENDED; cpu_src =3D gen_fp_ptr(REG(ext, 10)); } - round =3D 1; cpu_dest =3D gen_fp_ptr(REG(ext, 7)); switch (opmode) { case 0: case 0x40: case 0x44: /* fmove */ @@ -4485,11 +4589,9 @@ DISAS_INSN(fpu) break; case 1: /* fint */ gen_helper_firound(cpu_env, cpu_dest, cpu_src); - round =3D 0; break; case 3: /* fintrz */ gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src); - round =3D 0; break; case 4: case 0x41: case 0x45: /* fsqrt */ gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src); @@ -4513,40 +4615,16 @@ DISAS_INSN(fpu) gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest); break; case 0x38: /* fcmp */ - tcg_temp_free_ptr(cpu_dest); - cpu_dest =3D gen_fp_result_ptr(); - gen_helper_fsub_cmp(cpu_env, cpu_dest, cpu_src, cpu_dest); - round =3D 0; - break; + gen_helper_fcmp(cpu_env, cpu_src, cpu_dest); + return; case 0x3a: /* ftst */ - tcg_temp_free_ptr(cpu_dest); - cpu_dest =3D gen_fp_result_ptr(); - gen_fp_move(cpu_dest, cpu_src); - round =3D 0; - break; + gen_helper_ftst(cpu_env, cpu_src); + return; default: goto undef; } - if (round) { - if (opmode & 0x40) { - if ((opmode & 0x4) !=3D 0) - round =3D 0; - } else if ((s->fpcr & M68K_FPCR_PREC) =3D=3D 0) { - round =3D 0; - } - } - if (round) { - TCGv tmp =3D tcg_temp_new(); - gen_helper_redf32(tmp, cpu_env, cpu_dest); - gen_helper_extf32(cpu_env, cpu_dest, tmp); - tcg_temp_free(tmp); - } else { - TCGv_i64 t64 =3D tcg_temp_new_i64(); - gen_helper_redf64(t64, cpu_env, cpu_dest); - gen_helper_extf64(cpu_env, cpu_dest, t64); - tcg_temp_free_i64(t64); - } tcg_temp_free_ptr(cpu_src); + gen_helper_ftst(cpu_env, cpu_dest); tcg_temp_free_ptr(cpu_dest); return; undef: @@ -4559,9 +4637,8 @@ DISAS_INSN(fbcc) { uint32_t offset; uint32_t addr; - TCGv flag; TCGLabel *l1; - TCGv_ptr fp_result; + TCGv tmp, fpsr; =20 addr =3D s->pc; offset =3D cpu_ldsw_code(env, s->pc); @@ -4570,64 +4647,125 @@ DISAS_INSN(fbcc) offset =3D (offset << 16) | read_im16(env, s); } =20 + fpsr =3D tcg_temp_new(); + gen_load_fcr(s, fpsr, M68K_FPSR); l1 =3D gen_new_label(); /* TODO: Raise BSUN exception. */ - flag =3D tcg_temp_new(); - fp_result =3D gen_fp_result_ptr(); - gen_helper_fcompare(flag, cpu_env, fp_result); - tcg_temp_free_ptr(fp_result); /* Jump to l1 if condition is true. */ - switch (insn & 0xf) { - case 0: /* f */ + switch (insn & 0x3f) { + case 0: /* False */ + case 16: /* Signaling False */ break; - case 1: /* eq (=3D0) */ - tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1); + case 1: /* EQual Z */ + case 17: /* Signaling EQual Z */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_Z); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 2: /* ogt (=3D1) */ - tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(1), l1); + case 2: /* Ordered Greater Than !(A || Z || N) */ + case 18: /* Greater Than !(A || Z || N) */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, + FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); break; - case 3: /* oge (=3D0 or =3D1) */ - tcg_gen_brcond_i32(TCG_COND_LEU, flag, tcg_const_i32(1), l1); + case 3: /* Ordered Greater than or Equal Z || !(A || N) */ + case 19: /* Greater than or Equal Z || !(A || N) */ + assert(FPSR_CC_A =3D=3D (FPSR_CC_N >> 3)); + tmp =3D tcg_temp_new(); + tcg_gen_shli_i32(tmp, fpsr, 3); + tcg_gen_or_i32(tmp, tmp, fpsr); + tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N); + tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_Z); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 4: /* olt (=3D-1) */ - tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(0), l1); + case 4: /* Ordered Less Than !(!N || A || Z); */ + case 20: /* Less Than !(!N || A || Z); */ + tmp =3D tcg_temp_new(); + tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_N); + tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); break; - case 5: /* ole (=3D-1 or =3D0) */ - tcg_gen_brcond_i32(TCG_COND_LE, flag, tcg_const_i32(0), l1); + case 5: /* Ordered Less than or Equal Z || (N && !A) */ + case 21: /* Less than or Equal Z || (N && !A) */ + assert(FPSR_CC_A =3D=3D (FPSR_CC_N >> 3)); + tmp =3D tcg_temp_new(); + tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_A); + tcg_gen_shli_i32(tmp, tmp, 3); + tcg_gen_ori_i32(tmp, tmp, FPSR_CC_Z); + tcg_gen_and_i32(tmp, tmp, fpsr); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 6: /* ogl (=3D-1 or =3D1) */ - tcg_gen_andi_i32(flag, flag, 1); - tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1); + case 6: /* Ordered Greater or Less than !(A || Z) */ + case 22: /* Greater or Less than !(A || Z) */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); break; - case 7: /* or (=3D2) */ - tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1); + case 7: /* Ordered !A */ + case 23: /* Greater, Less or Equal !A */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); break; - case 8: /* un (<2) */ - tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(2), l1); + case 8: /* Unordered A */ + case 24: /* Not Greater, Less or Equal A */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 9: /* ueq (=3D0 or =3D2) */ - tcg_gen_andi_i32(flag, flag, 1); - tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1); + case 9: /* Unordered or Equal A || Z */ + case 25: /* Not Greater or Less then A || Z */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 10: /* ugt (>0) */ - tcg_gen_brcond_i32(TCG_COND_GT, flag, tcg_const_i32(0), l1); + case 10: /* Unordered or Greater Than A || !(N || Z)) */ + case 26: /* Not Less or Equal A || !(N || Z)) */ + assert(FPSR_CC_Z =3D=3D (FPSR_CC_N >> 1)); + tmp =3D tcg_temp_new(); + tcg_gen_shli_i32(tmp, fpsr, 1); + tcg_gen_or_i32(tmp, tmp, fpsr); + tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N); + tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_A); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 11: /* uge (>=3D0) */ - tcg_gen_brcond_i32(TCG_COND_GE, flag, tcg_const_i32(0), l1); + case 11: /* Unordered or Greater or Equal A || Z || !N */ + case 27: /* Not Less Than A || Z || !N */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); + tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 12: /* ult (=3D-1 or =3D2) */ - tcg_gen_brcond_i32(TCG_COND_GEU, flag, tcg_const_i32(2), l1); + case 12: /* Unordered or Less Than A || (N && !Z) */ + case 28: /* Not Greater than or Equal A || (N && !Z) */ + assert(FPSR_CC_Z =3D=3D (FPSR_CC_N >> 1)); + tmp =3D tcg_temp_new(); + tcg_gen_xori_i32(tmp, fpsr, FPSR_CC_Z); + tcg_gen_shli_i32(tmp, tmp, 1); + tcg_gen_ori_i32(tmp, tmp, FPSR_CC_A); + tcg_gen_and_i32(tmp, tmp, fpsr); + tcg_gen_andi_i32(tmp, tmp, FPSR_CC_A | FPSR_CC_N); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 13: /* ule (!=3D1) */ - tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(1), l1); + case 13: /* Unordered or Less or Equal A || Z || N */ + case 29: /* Not Greater Than A || Z || N */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); + tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); break; - case 14: /* ne (!=3D0) */ - tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1); + case 14: /* Not Equal !Z */ + case 30: /* Signaling Not Equal !Z */ + tmp =3D tcg_temp_new(); + tcg_gen_andi_i32(tmp, fpsr, FPSR_CC_Z); + tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); break; - case 15: /* t */ + case 15: /* True */ + case 31: /* Signaling True */ tcg_gen_br(l1); break; } + tcg_temp_free(fpsr); gen_jmp_tb(s, 0, s->pc); gen_set_label(l1); gen_jmp_tb(s, 1, addr + offset); @@ -5252,7 +5390,6 @@ void gen_intermediate_code(CPUM68KState *env, Transla= tionBlock *tb) dc->cc_op =3D CC_OP_DYNAMIC; dc->cc_op_synced =3D 1; dc->singlestep_enabled =3D cs->singlestep_enabled; - dc->fpcr =3D env->fpcr; dc->user =3D (env->sr & SR_S) =3D=3D 0; dc->done_mac =3D 0; dc->writeback_mask =3D 0; @@ -5371,6 +5508,38 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fpri= ntf_function cpu_fprintf, cpu_fprintf(f, "SR =3D %04x %c%c%c%c%c ", sr, (sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-'); + cpu_fprintf(f, "FPSR =3D %08x %c%c%c%c ", env->fpsr, + (env->fpsr & FPSR_CC_A) ? 'A' : '-', + (env->fpsr & FPSR_CC_I) ? 'I' : '-', + (env->fpsr & FPSR_CC_Z) ? 'Z' : '-', + (env->fpsr & FPSR_CC_N) ? 'N' : '-'); + cpu_fprintf(f, "\n " + "FPCR =3D %04x ", env->fpcr); + switch (env->fpcr & FPCR_PREC_MASK) { + case FPCR_PREC_X: + cpu_fprintf(f, "X "); + break; + case FPCR_PREC_S: + cpu_fprintf(f, "S "); + break; + case FPCR_PREC_D: + cpu_fprintf(f, "D "); + break; + } + switch (env->fpcr & FPCR_RND_MASK) { + case FPCR_RND_N: + cpu_fprintf(f, "RN "); + break; + case FPCR_RND_Z: + cpu_fprintf(f, "RZ "); + break; + case FPCR_RND_M: + cpu_fprintf(f, "RM "); + break; + case FPCR_RND_P: + cpu_fprintf(f, "RP "); + break; + } } =20 void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, --=20 2.9.4 From nobody Sat May 4 15:20:10 2024 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.zoho.com; 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; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1497992156802614.5322778752212; Tue, 20 Jun 2017 13:55:56 -0700 (PDT) Received: from localhost ([::1]:50626 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQBn-0002zJ-Bg for importer@patchew.org; Tue, 20 Jun 2017 16:55:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dNQ87-0008EZ-7Y for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dNQ84-0004H6-JB for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:07 -0400 Received: from mout.kundenserver.de ([212.227.17.24]:57635) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dNQ84-0004GF-8C for qemu-devel@nongnu.org; Tue, 20 Jun 2017 16:52:04 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104 [212.227.15.183]) with ESMTPSA (Nemesis) id 0LxOmo-1dqXWr0A7W-01707r; Tue, 20 Jun 2017 22:51:31 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Tue, 20 Jun 2017 22:51:21 +0200 Message-Id: <20170620205121.26515-7-laurent@vivier.eu> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170620205121.26515-1-laurent@vivier.eu> References: <20170620205121.26515-1-laurent@vivier.eu> X-Provags-ID: V03:K0:yn85rJvzsLAFn+Zg2LWs41Fh2MNP/BatUbjHr9UXXSmZUMpD7Sr NFgGenvK5WjvtH1A8uAx+ZhNPwmfNvE3j5201cuzQN//29ek7zR04UlWib6cibmTCpPheHf NRt6UZ4+mbS33MO3q8fwkIQ5EGWprYpev8SpoAOF6QTq8VCCWAhbRrdZryh55W4aWUV4wqA tJ7nHMpS4OxGiEpccF1VA== X-UI-Out-Filterresults: notjunk:1;V01:K0:/3MWe/EXLWc=:qEgsPtzQesrzSSXluNxXi2 zZVGxHuKc9KmNEj33a670R8JHTlk9PhUst1erWWykVNlo2o3Hcj7xFErKTUwyQLZLo/agfRD8 +pwbbMSkGm0zrH/BT+14GjaYJrLNFbrIXCwG2BacZDrMyQIfz3UY3s4A/mVaiPOrA6/QxpfTl InOWLY7kTEH0Ok863yR/CUhULaPdi1/7jw1x5DlOyuVZtj58/MxUOLEE7+56yw3eUlg6vpyaO HqZsMe9OOxNirvxIUoty6Uv6EmginxFJAFh6k+B/jxl9rSyONJhIVDpkxpecUyLvM7vOaj85D Qju7K3aP1/9zl4NovdRsG2hQrTkpGuqbGtn4fUi6xBKbf3Sy9DGe1tZ+LpITg+17zrQi0iLbJ gNz4JFWY1x6B05hiqEQ71e3FPg82BDjn3bYkAnlJ0xWQCHAUN2IVWjolaSXecuKq6O2GS+aom bK0moznDQElzDbyGu0WreYLHC2lQnXc8wP+uvpCBRL6MDBdJCzjdBaeCvUm5iH0cjJTuYEjNe gOx+5NVSttKjk0uMbo2Y3IoyVEKoGtFCor1lOHs3bbk8mDqUSl1zeT8bSGmG2b3xMbZM6fUbC mOJooEXdjyWEo+BGzLiGQ1ESHPNj4wpyUIkW78dIfp5AAa8r4J6L6ueP8Ci2CPEdJE8VsnrjU RWa5KjlDo3KzGIkbk68xQUe/hLOMj0IsfsI2D9Y+DKorPlCY+/GFK+vJvvqJpCCoJaDM= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.24 Subject: [Qemu-devel] [PATCH v5 6/6] target-m68k, linux-user: manage FP registers in ucontext 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: Thomas Huth , Riku Voipio , Laurent Vivier , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Laurent Vivier --- linux-user/signal.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/linux-user/signal.c b/linux-user/signal.c index 3d18d1b..d3753e4 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5673,6 +5673,24 @@ give_sigsegv: force_sigsegv(sig); } =20 +static inline void target_rt_save_fpu_state(struct target_ucontext *uc, + CPUM68KState *env) +{ + int i; + target_fpregset_t *fpregs =3D &uc->tuc_mcontext.fpregs; + + __put_user(env->fpcr, &fpregs->f_fpcntl[0]); + __put_user(env->fpsr, &fpregs->f_fpcntl[1]); + /* fpiar is not emulated */ + + for (i =3D 0; i < 8; i++) { + uint32_t high =3D env->fregs[i].d.high << 16; + __put_user(high, &fpregs->f_fpregs[i * 3]); + __put_user(env->fregs[i].d.low, + (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]); + } +} + static inline int target_rt_setup_ucontext(struct target_ucontext *uc, CPUM68KState *env) { @@ -5699,9 +5717,30 @@ static inline int target_rt_setup_ucontext(struct ta= rget_ucontext *uc, __put_user(env->pc, &gregs[16]); __put_user(sr, &gregs[17]); =20 + target_rt_save_fpu_state(uc, env); + return 0; } =20 +static inline void target_rt_restore_fpu_state(CPUM68KState *env, + struct target_ucontext *uc) +{ + int i; + target_fpregset_t *fpregs =3D &uc->tuc_mcontext.fpregs; + + __get_user(env->fpcr, &fpregs->f_fpcntl[0]); + __get_user(env->fpsr, &fpregs->f_fpcntl[1]); + /* fpiar is not emulated */ + + for (i =3D 0; i < 8; i++) { + uint32_t high; + __get_user(high, &fpregs->f_fpregs[i * 3]); + env->fregs[i].d.high =3D high >> 16; + __get_user(env->fregs[i].d.low, + (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]); + } +} + static inline int target_rt_restore_ucontext(CPUM68KState *env, struct target_ucontext *uc) { @@ -5733,6 +5772,8 @@ static inline int target_rt_restore_ucontext(CPUM68KS= tate *env, __get_user(temp, &gregs[17]); cpu_m68k_set_ccr(env, temp); =20 + target_rt_restore_fpu_state(env, uc); + return 0; =20 badframe: --=20 2.9.4