From patchwork Thu Dec 31 20:41:07 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 42219 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id F3345B6EF2 for ; Wed, 6 Jan 2010 09:58:03 +1100 (EST) Received: from localhost ([127.0.0.1]:45774 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NSILg-000766-0K for incoming@patchwork.ozlabs.org; Tue, 05 Jan 2010 17:58:00 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NSFVo-0003ET-T5 for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:56:17 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NSFVY-0002xt-Gi for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:56:05 -0500 Received: from [199.232.76.173] (port=43106 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NSFVV-0002ub-TF for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:55:58 -0500 Received: from mx20.gnu.org ([199.232.41.8]:36480) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NSFVR-0005Iy-Q0 for qemu-devel@nongnu.org; Tue, 05 Jan 2010 14:55:54 -0500 Received: from are.twiddle.net ([75.149.56.221]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NRwAo-0007xU-5G for qemu-devel@nongnu.org; Mon, 04 Jan 2010 18:17:18 -0500 Received: by are.twiddle.net (Postfix, from userid 5000) id AC2F6E21; Mon, 4 Jan 2010 15:08:37 -0800 (PST) Message-Id: In-Reply-To: References: From: Richard Henderson Date: Thu, 31 Dec 2009 12:41:07 -0800 To: qemu-devel@nongnu.org X-detected-operating-system: by mx20.gnu.org: GNU/Linux 2.6 (newer, 2) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: laurent.desnogues@gmail.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 2/6] target-alpha: Split up FPCR value into separate fields. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The fpcr_exc_status, fpcr_exc_mask, and fpcr_dyn_round fields are stored in format for convenience during regular execution. Revert the addition of float_exception_mask to float_status, added in ba0e276db4b51bd2255a5d5ff8902c70d32ade40. Signed-off-by: Richard Henderson --- fpu/softfloat.h | 1 - target-alpha/cpu.h | 24 ++++++-- target-alpha/helper.c | 167 +++++++++++++++++++++++++++++++++---------------- 3 files changed, 131 insertions(+), 61 deletions(-) diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 9d82694..636591b 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -187,7 +187,6 @@ typedef struct float_status { signed char float_detect_tininess; signed char float_rounding_mode; signed char float_exception_flags; - signed char float_exception_mask; #ifdef FLOATX80 signed char floatx80_rounding_precision; #endif diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index c0dff4b..4722415 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -145,6 +145,10 @@ enum { #define FPCR_UNFD (1ULL << 61) #define FPCR_UNDZ (1ULL << 60) #define FPCR_DYN_SHIFT 58 +#define FPCR_DYN_CHOPPED (0ULL << FPCR_DYN_SHIFT) +#define FPCR_DYN_MINUS (1ULL << FPCR_DYN_SHIFT) +#define FPCR_DYN_NORMAL (2ULL << FPCR_DYN_SHIFT) +#define FPCR_DYN_PLUS (3ULL << FPCR_DYN_SHIFT) #define FPCR_DYN_MASK (3ULL << FPCR_DYN_SHIFT) #define FPCR_IOV (1ULL << 57) #define FPCR_INE (1ULL << 56) @@ -341,17 +345,27 @@ struct pal_handler_t { struct CPUAlphaState { uint64_t ir[31]; - float64 fir[31]; - float_status fp_status; - uint64_t fpcr; + float64 fir[31]; uint64_t pc; uint64_t lock; uint32_t pcc[2]; uint64_t ipr[IPR_LAST]; uint64_t ps; uint64_t unique; - int saved_mode; /* Used for HW_LD / HW_ST */ - int intr_flag; /* For RC and RS */ + float_status fp_status; + /* The following fields make up the FPCR, but in FP_STATUS format. */ + uint8_t fpcr_exc_status; + uint8_t fpcr_exc_mask; + uint8_t fpcr_dyn_round; + uint8_t fpcr_flush_to_zero; + uint8_t fpcr_dnz; + uint8_t fpcr_dnod; + uint8_t fpcr_undz; + + /* Used for HW_LD / HW_ST */ + uint8_t saved_mode; + /* For RC and RS */ + uint8_t intr_flag; #if TARGET_LONG_BITS > HOST_LONG_BITS /* temporary fixed-point registers diff --git a/target-alpha/helper.c b/target-alpha/helper.c index be7d37b..57830e4 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -27,79 +27,136 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env) { - uint64_t ret = 0; - int flags, mask; - - flags = env->fp_status.float_exception_flags; - ret |= (uint64_t) flags << 52; - if (flags) - ret |= FPCR_SUM; - env->ipr[IPR_EXC_SUM] &= ~0x3E; - env->ipr[IPR_EXC_SUM] |= flags << 1; - - mask = env->fp_status.float_exception_mask; - if (mask & float_flag_invalid) - ret |= FPCR_INVD; - if (mask & float_flag_divbyzero) - ret |= FPCR_DZED; - if (mask & float_flag_overflow) - ret |= FPCR_OVFD; - if (mask & float_flag_underflow) - ret |= FPCR_UNFD; - if (mask & float_flag_inexact) - ret |= FPCR_INED; - - switch (env->fp_status.float_rounding_mode) { + uint64_t r = 0; + uint8_t t; + + t = env->fpcr_exc_status; + if (t) { + r = FPCR_SUM; + if (t & float_flag_invalid) { + r |= FPCR_INV; + } + if (t & float_flag_divbyzero) { + r |= FPCR_DZE; + } + if (t & float_flag_overflow) { + r |= FPCR_OVF; + } + if (t & float_flag_underflow) { + r |= FPCR_UNF; + } + if (t & float_flag_inexact) { + r |= FPCR_INE; + } + } + + t = env->fpcr_exc_mask; + if (t & float_flag_invalid) { + r |= FPCR_INVD; + } + if (t & float_flag_divbyzero) { + r |= FPCR_DZED; + } + if (t & float_flag_overflow) { + r |= FPCR_OVFD; + } + if (t & float_flag_underflow) { + r |= FPCR_UNFD; + } + if (t & float_flag_inexact) { + r |= FPCR_INED; + } + + switch (env->fpcr_dyn_round) { case float_round_nearest_even: - ret |= 2ULL << FPCR_DYN_SHIFT; + r |= FPCR_DYN_NORMAL; break; case float_round_down: - ret |= 1ULL << FPCR_DYN_SHIFT; + r |= FPCR_DYN_MINUS; break; case float_round_up: - ret |= 3ULL << FPCR_DYN_SHIFT; + r |= FPCR_DYN_PLUS; break; case float_round_to_zero: + r |= FPCR_DYN_CHOPPED; break; } - return ret; + + if (env->fpcr_dnz) { + r |= FPCR_DNZ; + } + if (env->fpcr_dnod) { + r |= FPCR_DNOD; + } + if (env->fpcr_undz) { + r |= FPCR_UNDZ; + } + + return r; } void cpu_alpha_store_fpcr (CPUState *env, uint64_t val) { - int round_mode, mask; + uint8_t t; - set_float_exception_flags((val >> 52) & 0x3F, &env->fp_status); + t = 0; + if (val & FPCR_INV) { + t |= float_flag_invalid; + } + if (val & FPCR_DZE) { + t |= float_flag_divbyzero; + } + if (val & FPCR_OVF) { + t |= float_flag_overflow; + } + if (val & FPCR_UNF) { + t |= float_flag_underflow; + } + if (val & FPCR_INE) { + t |= float_flag_inexact; + } + env->fpcr_exc_status = t; - mask = 0; - if (val & FPCR_INVD) - mask |= float_flag_invalid; - if (val & FPCR_DZED) - mask |= float_flag_divbyzero; - if (val & FPCR_OVFD) - mask |= float_flag_overflow; - if (val & FPCR_UNFD) - mask |= float_flag_underflow; - if (val & FPCR_INED) - mask |= float_flag_inexact; - env->fp_status.float_exception_mask = mask; + t = 0; + if (val & FPCR_INVD) { + t |= float_flag_invalid; + } + if (val & FPCR_DZED) { + t |= float_flag_divbyzero; + } + if (val & FPCR_OVFD) { + t |= float_flag_overflow; + } + if (val & FPCR_UNFD) { + t |= float_flag_underflow; + } + if (val & FPCR_INED) { + t |= float_flag_inexact; + } + env->fpcr_exc_mask = t; - switch ((val >> FPCR_DYN_SHIFT) & 3) { - case 0: - round_mode = float_round_to_zero; + switch (val & FPCR_DYN_MASK) { + case FPCR_DYN_CHOPPED: + t = float_round_to_zero; break; - case 1: - round_mode = float_round_down; + case FPCR_DYN_MINUS: + t = float_round_down; break; - case 2: - round_mode = float_round_nearest_even; + case FPCR_DYN_NORMAL: + t = float_round_nearest_even; break; - case 3: - default: /* this avoids a gcc (< 4.4) warning */ - round_mode = float_round_up; + case FPCR_DYN_PLUS: + t = float_round_up; break; } - set_float_rounding_mode(round_mode, &env->fp_status); + env->fpcr_dyn_round = t; + + env->fpcr_flush_to_zero + = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD); + + env->fpcr_dnz = (val & FPCR_DNZ) != 0; + env->fpcr_dnod = (val & FPCR_DNOD) != 0; + env->fpcr_undz = (val & FPCR_UNDZ) != 0; } #if defined(CONFIG_USER_ONLY)