From patchwork Thu Sep 27 23:15:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 187541 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 996D02C007C for ; Fri, 28 Sep 2012 09:15:21 +1000 (EST) Received: from localhost ([::1]:43674 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1THNId-0006pt-Ml for incoming@patchwork.ozlabs.org; Thu, 27 Sep 2012 19:15:19 -0400 Received: from eggs.gnu.org ([208.118.235.92]:56142) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1THNIT-0006n0-S5 for qemu-devel@nongnu.org; Thu, 27 Sep 2012 19:15:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1THNIR-0006AG-Aq for qemu-devel@nongnu.org; Thu, 27 Sep 2012 19:15:09 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:33023) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1THNIR-00069K-0x for qemu-devel@nongnu.org; Thu, 27 Sep 2012 19:15:07 -0400 Received: by pbbrp2 with SMTP id rp2so4292929pbb.4 for ; Thu, 27 Sep 2012 16:15:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=XXABVgrrrNPzfHWmH50xUuffqkkRWbIxLNVCd7Zcs9o=; b=zIGZG1JlLTPccjqsGsO3dju4TRY11+r4OaIxf1KdzhPWRqzQpKhEm+CsCuZdtWyGWV xel9ls+LAoQI2n1bG1hdzwh4G0mwPN1Zo3zSqVKdtHvh7jJ3Qwc6P27Qj4Gnx8jAemqQ Eo8dRBUP64ZoAxvKTqNE2SBwJFvj4rpcJQyQ9YRm0TRLaks9uMwIikY4PsN2DOqGJ/gh cItWpttaxdDXrMjQEznPHhrcYOrmd2jX4h9sl6CMTxzBtZ1A9ba3EvJuGjHvR0amkaOn 5mG1L+BfJd4YhY7Xb60djZCmMiLjwrOsLEGbhnJTcHiwwek1amIUGBRQS5oUwqIzVwWh TZiA== Received: by 10.66.81.231 with SMTP id d7mr13075211pay.50.1348787706437; Thu, 27 Sep 2012 16:15:06 -0700 (PDT) Received: from anchor.twiddle.home.com ([173.160.232.49]) by mx.google.com with ESMTPS id l6sm2499595pav.12.2012.09.27.16.15.05 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Sep 2012 16:15:05 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 27 Sep 2012 16:15:02 -0700 Message-Id: <1348787702-24115-1-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1348785610-23418-1-git-send-email-rth@twiddle.net> References: <1348785610-23418-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.160.45 Cc: Alexander Graf Subject: [Qemu-devel] [PATCH 037/147] target-s390: Send signals for divide 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+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Richard Henderson --- target-s390x/cpu.h | 2 ++ target-s390x/int_helper.c | 51 ++++++++++++++++++++++++++++++++++++++++------ target-s390x/misc_helper.c | 23 +++++++++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 630198f..5b6df0e 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -940,5 +940,7 @@ uint32_t set_cc_nz_f64(float64 v); /* misc_helper.c */ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); +void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, + uintptr_t retaddr); #endif diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c index fe1cb87..f2f420c 100644 --- a/target-s390x/int_helper.c +++ b/target-s390x/int_helper.c @@ -38,22 +38,54 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2) } /* 64/32 -> 32 signed division */ -int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b) +int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64) { - env->retxl = a % (int32_t)b; - return a / (int32_t)b; + int32_t ret, b = b64; + int64_t q; + + if (b == 0) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + ret = q = a / b; + env->retxl = a % b; + + /* Catch non-representable quotient. */ + if (ret != q) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + return ret; } /* 64/32 -> 32 unsigned division */ -uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b) +uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64) { - env->retxl = a % (uint32_t)b; - return a / (uint32_t)b; + uint32_t ret, b = b64; + uint64_t q; + + if (b == 0) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + ret = q = a / b; + env->retxl = a % b; + + /* Catch non-representable quotient. */ + if (ret != q) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + return ret; } /* 64/64 -> 64 signed division */ int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b) { + /* Catch divide by zero, and non-representable quotient (MIN / -1). */ + if (b == 0 || (b == -1 && a == (1ll << 63))) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } env->retxl = a % b; return a / b; } @@ -63,6 +95,10 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t b) { uint64_t ret; + /* Signal divide by zero. */ + if (b == 0) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } if (ah == 0) { /* 64 -> 64/64 case */ env->retxl = al % b; @@ -75,6 +111,9 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, __uint128_t q = a / b; env->retxl = a % b; ret = q; + if (ret != q) { + runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC()); + } #else /* 32-bit hosts would need special wrapper functionality - just abort if we encounter such a case; it's very unlikely anyways. */ diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index bd5fd20..aec222c 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -42,6 +42,29 @@ #define HELPER_LOG(x...) #endif +/* Raise an exception dynamically from a helper function. */ +void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, + uintptr_t retaddr) +{ + TranslationBlock *tb; + int t; + + env->exception_index = EXCP_PGM; + env->int_pgm_code = excp; + + /* Use the (ultimate) callers address to find the insn that trapped. */ + tb = tb_find_pc(retaddr); + assert(tb != NULL); + cpu_restore_state(tb, env, retaddr); + + /* Advance past the insn. */ + t = cpu_ldub_code(env, env->psw.addr); + env->int_pgm_ilen = t = get_ilen(t); + env->psw.addr += 2 * t; + + cpu_loop_exit(env); +} + /* Raise an exception statically from a TB. */ void HELPER(exception)(CPUS390XState *env, uint32_t excp) {