From patchwork Fri Jan 29 18:40:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jessica Clarke X-Patchwork-Id: 8166481 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B92DC9F440 for ; Fri, 29 Jan 2016 18:42:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BB4CF20382 for ; Fri, 29 Jan 2016 18:42:04 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B4ED820381 for ; Fri, 29 Jan 2016 18:42:03 +0000 (UTC) Received: from localhost ([::1]:36167 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aPDzf-0005UD-4E for patchwork-qemu-devel@patchwork.kernel.org; Fri, 29 Jan 2016 13:42:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36389) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aPDyM-0001aX-FN for qemu-devel@nongnu.org; Fri, 29 Jan 2016 13:40:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aPDyK-0007aG-FF for qemu-devel@nongnu.org; Fri, 29 Jan 2016 13:40:42 -0500 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]:35306) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aPDyK-0007Z5-5F for qemu-devel@nongnu.org; Fri, 29 Jan 2016 13:40:40 -0500 Received: by mail-wm0-x244.google.com with SMTP id l66so11421022wml.2 for ; Fri, 29 Jan 2016 10:40:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jrtc27.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9UPgxu22CS2litK447DbThg55/s5QYZJYSQQWT+y4VI=; b=MMu3fiLtzG6HQuPUwuUKHbsxhoHPkxm7z7e4ygLWd1AChSuj2epNrVUt3aG/ZGn3bc 65FNgT6fY+kpBS6MT6TXH4svapoz7R4Dp1GpBQEt5dL+lF7/0NinjJXCHqfLzGljZOvM 10ZZkDQ0/Vf2956sC387Tcb7W1QH9KKMkX++E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9UPgxu22CS2litK447DbThg55/s5QYZJYSQQWT+y4VI=; b=TjIqO1SXV+Q9k9uWdgEJ3HuJEIEpyHwTpQ7ROKRx3bsVvmcmFPLxB8qaZ1VFz7hRMs kBj0qheEBkST2a8zth47lLh1g5tgfWmTS8cwb+dUmfiWq28PzdKvhgeyliKmyGBDvqd8 +adlTfr1hA9LtseLzQ7bQ2DeJw56dF2psSlkxbzzRKzFx/TqSMeM/1WMmsaYNraHia3B Ec3ZkvGIcJ+f+jbo9FjBAtv6L1gRVt4ghDVfa3ge9KBsL90GhkoQ7VX5HyTbG4GDrHoI 0+wVH/a+mbXOmYJqScJhB1Th7Lhyn77MllXz3aSZ5STw9KmzUuhcDGe9Bn7lOEyveDyE prVw== X-Gm-Message-State: AG10YORCOdAZIzof0XD6DO/csjhDLw4YA+zVlWkw0KwARDYNRP5QDSSC1MkzzVWHyM88GA== X-Received: by 10.28.158.198 with SMTP id h189mr7090317wme.74.1454092839504; Fri, 29 Jan 2016 10:40:39 -0800 (PST) Received: from localhost.localdomain (global-184-8.nat-1.net.cam.ac.uk. [131.111.184.8]) by smtp.gmail.com with ESMTPSA id n5sm8685996wmf.3.2016.01.29.10.40.38 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 29 Jan 2016 10:40:38 -0800 (PST) From: James Clarke To: qemu-devel@nongnu.org Date: Fri, 29 Jan 2016 18:40:21 +0000 Message-Id: <1454092821-46795-3-git-send-email-jrtc27@jrtc27.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1454092821-46795-1-git-send-email-jrtc27@jrtc27.com> References: <1454092821-46795-1-git-send-email-jrtc27@jrtc27.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::244 Cc: James Clarke , qemu-ppc@nongnu.org, david@gibson.dropbear.id.au Subject: [Qemu-devel] [PATCH v2 2/2] target-ppc: mcrfs should always update FEX/VX and only clear exception bits X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Here is the description of the mcrfs instruction from the PowerPC Architecture Book, Version 2.02, Book I: PowerPC User Instruction Set Architecture (http://www.ibm.com/developerworks/systems/library/es-archguide-v2.html), found on page 120: The contents of FPSCR field BFA are copied to Condition Register field BF. All exception bits copied are set to 0 in the FPSCR. If the FX bit is copied, it is set to 0 in the FPSCR. Special Registers Altered: CR field BF FX OX (if BFA=0) UX ZX XX VXSNAN (if BFA=1) VXISI VXIDI VXZDZ VXIMZ (if BFA=2) VXVC (if BFA=3) VXSOFT VXSQRT VXCVI (if BFA=5) However, currently every bit in FPSCR field BFA is set to 0, including ones not on that list. This can be seen in the following simple C program: #include #include int main(int argc, char **argv) { int ret; ret = fegetround(); printf("Current rounding: %d\n", ret); ret = fesetround(FE_UPWARD); printf("Setting to FE_UPWARD (%d): %d\n", FE_UPWARD, ret); ret = fegetround(); printf("Current rounding: %d\n", ret); ret = fegetround(); printf("Current rounding: %d\n", ret); return 0; } which gave the output (before this commit): Current rounding: 0 Setting to FE_UPWARD (2): 0 Current rounding: 2 Current rounding: 0 instead of (after this commit): Current rounding: 0 Setting to FE_UPWARD (2): 0 Current rounding: 2 Current rounding: 2 The relevant disassembly is in fegetround(), which, on my system, is: __GI___fegetround: <+0>: mcrfs cr7, cr7 <+4>: mfcr r3 <+8>: clrldi r3, r3, 62 <+12>: blr What happens is that, the first time fegetround() is called, FPSCR field 7 is retrieved. However, because of the bug in mcrfs, the entirety of field 7 is set to 0, which includes the rounding mode. There are other issues this will fix, such as condition flags not persisting when they should if read, and if you were to read a specific field with some exception bits set, but no others were set in the entire register, then the bits would be cleared correctly, but FEX/VX would not be updated to 0 as they should be. Signed-off-by: James Clarke --- target-ppc/cpu.h | 6 ++++++ target-ppc/translate.c | 21 +++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 3a967b7..d811bc9 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -718,6 +718,12 @@ enum { #define FP_RN1 (1ull << FPSCR_RN1) #define FP_RN (1ull << FPSCR_RN) +/* the exception bits which can be cleared by mcrfs - includes FX */ +#define FP_EX_CLEAR_BITS (FP_FX | FP_OX | FP_UX | FP_ZX | \ + FP_XX | FP_VXSNAN | FP_VXISI | FP_VXIDI | \ + FP_VXZDZ | FP_VXIMZ | FP_VXVC | FP_VXSOFT | \ + FP_VXSQRT | FP_VXCVI) + /*****************************************************************************/ /* Vector status and control register */ #define VSCR_NJ 16 /* Vector non-java */ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 4be7eaa..ca10bd1 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -2500,18 +2500,31 @@ static void gen_fmrgow(DisasContext *ctx) static void gen_mcrfs(DisasContext *ctx) { TCGv tmp = tcg_temp_new(); + TCGv_i32 tmask; + TCGv_i64 tnew_fpscr = tcg_temp_new_i64(); int bfa; + int nibble; + int shift; if (unlikely(!ctx->fpu_enabled)) { gen_exception(ctx, POWERPC_EXCP_FPU); return; } - bfa = 4 * (7 - crfS(ctx->opcode)); - tcg_gen_shri_tl(tmp, cpu_fpscr, bfa); + bfa = crfS(ctx->opcode); + nibble = 7 - bfa; + shift = 4 * nibble; + tcg_gen_shri_tl(tmp, cpu_fpscr, shift); tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); - tcg_temp_free(tmp); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf); - tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); + tcg_temp_free(tmp); + tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr); + /* Only the exception bits (including FX) should be cleared if read */ + tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS)); + /* FEX and VX need to be updated, so don't set fpscr directly */ + tmask = tcg_const_i32(1 << nibble); + gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask); + tcg_temp_free_i32(tmask); + tcg_temp_free_i64(tnew_fpscr); } /* mffs */