From patchwork Mon May 29 19:24:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 9753537 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DE69C60249 for ; Mon, 29 May 2017 19:31:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB00D26E47 for ; Mon, 29 May 2017 19:31:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AFE6B27E71; Mon, 29 May 2017 19:31:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 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.wl.linuxfoundation.org (Postfix) with ESMTPS id 4BF6E26E47 for ; Mon, 29 May 2017 19:31:38 +0000 (UTC) Received: from localhost ([::1]:50188 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dFQO9-0002jt-EP for patchwork-qemu-devel@patchwork.kernel.org; Mon, 29 May 2017 15:31:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38809) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dFQHc-0006Tt-0r for qemu-devel@nongnu.org; Mon, 29 May 2017 15:24:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dFQHa-00074S-AK for qemu-devel@nongnu.org; Mon, 29 May 2017 15:24:52 -0400 Received: from hall.aurel32.net ([2001:bc8:30d7:100::1]:42878) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dFQHZ-00072J-Vz for qemu-devel@nongnu.org; Mon, 29 May 2017 15:24:50 -0400 Received: from [2001:bc8:30d7:120:9bb5:8936:7e6a:9e36] (helo=ohm.rr44.fr) by hall.aurel32.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1dFQHX-0007N3-H4; Mon, 29 May 2017 21:24:47 +0200 Received: from aurel32 by ohm.rr44.fr with local (Exim 4.89) (envelope-from ) id 1dFQHV-0001bi-SU; Mon, 29 May 2017 21:24:45 +0200 From: Aurelien Jarno To: qemu-devel@nongnu.org Date: Mon, 29 May 2017 21:24:28 +0200 Message-Id: <20170529192440.5990-18-aurelien@aurel32.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170529192440.5990-1-aurelien@aurel32.net> References: <20170529192440.5990-1-aurelien@aurel32.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:bc8:30d7:100::1 Subject: [Qemu-devel] [PATCH v2 17/29] target/s390x: fix COMPARE LOGICAL LONG EXTENDED 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: Alexander Graf , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP There are multiple issues with the COMPARE LOGICAL LONG EXTENDED instruction: - The test between the two operands is inverted, leading to an inversion of the cc values 1 and 2. - The address and length of an operand continue to be decreased after reaching the end of this operand. These values are then wrong write back to the registers. - We should limit the amount of bytes to process, so that interrupts can be served correctly. At the same time rename dest into src1 and src into src3 to match the operand names and make the code less confusing. Signed-off-by: Aurelien Jarno Reviewed-by: Richard Henderson --- target/s390x/mem_helper.c | 54 ++++++++++++++++++++++++++++++++--------------- target/s390x/translate.c | 20 +++++++++++++----- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 911c3d7f8e..b3a2ce2252 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -666,35 +666,55 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3) { uintptr_t ra = GETPC(); - uint64_t destlen = get_length(env, r1 + 1); - uint64_t dest = get_address(env, r1); - uint64_t srclen = get_length(env, r3 + 1); - uint64_t src = get_address(env, r3); + uint64_t src1len = get_length(env, r1 + 1); + uint64_t src1 = get_address(env, r1); + uint64_t src3len = get_length(env, r3 + 1); + uint64_t src3 = get_address(env, r3); uint8_t pad = a2 & 0xff; + uint64_t len = MAX(src1len, src3len); uint32_t cc = 0; - if (!(destlen || srclen)) { + if (!len) { return cc; } - if (srclen > destlen) { - srclen = destlen; + /* Lest we fail to service interrupts in a timely manner, limit the + amount of work we're willing to do. For now, let's cap at 8k. */ + if (len > 0x2000) { + len = 0x2000; + cc = 3; } - for (; destlen || srclen; src++, dest++, destlen--, srclen--) { - uint8_t v1 = srclen ? cpu_ldub_data_ra(env, src, ra) : pad; - uint8_t v2 = destlen ? cpu_ldub_data_ra(env, dest, ra) : pad; - if (v1 != v2) { - cc = (v1 < v2) ? 1 : 2; + for (; len; len--) { + uint8_t v1 = pad; + uint8_t v3 = pad; + + if (src1len) { + v1 = cpu_ldub_data_ra(env, src1, ra); + } + if (src3len) { + v3 = cpu_ldub_data_ra(env, src3, ra); + } + + if (v1 != v3) { + cc = (v1 < v3) ? 1 : 2; break; } + + if (src1len) { + src1++; + src1len--; + } + if (src3len) { + src3++; + src3len--; + } } - set_length(env, r1 + 1, destlen); - /* can't use srclen here, we trunc'ed it */ - set_length(env, r3 + 1, env->regs[r3 + 1] - src - env->regs[r3]); - set_address(env, r1, dest); - set_address(env, r3, src); + set_length(env, r1 + 1, src1len); + set_length(env, r3 + 1, src3len); + set_address(env, r1, src1); + set_address(env, r3, src3); return cc; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 95ca53c1ef..9309e58009 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -1917,11 +1917,21 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o) static ExitStatus op_clcle(DisasContext *s, DisasOps *o) { - TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); - TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); - gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3); - tcg_temp_free_i32(r1); - tcg_temp_free_i32(r3); + int r1 = get_field(s->fields, r1); + int r3 = get_field(s->fields, r3); + TCGv_i32 t1, t3; + + /* r1 and r3 must be even. */ + if (r1 & 1 || r3 & 1) { + gen_program_exception(s, PGM_SPECIFICATION); + return EXIT_NORETURN; + } + + t1 = tcg_const_i32(r1); + t3 = tcg_const_i32(r3); + gen_helper_clcle(cc_op, cpu_env, t1, o->in2, t3); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t3); set_cc_static(s); return NO_EXIT; }