From patchwork Fri Sep 28 00:09:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 187598 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 248B12C00B5 for ; Fri, 28 Sep 2012 10:09:46 +1000 (EST) Received: from localhost ([::1]:47363 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1THO9I-0005rW-7K for incoming@patchwork.ozlabs.org; Thu, 27 Sep 2012 20:09:44 -0400 Received: from eggs.gnu.org ([208.118.235.92]:34298) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1THO95-0005rB-N1 for qemu-devel@nongnu.org; Thu, 27 Sep 2012 20:09:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1THO92-0006vB-FD for qemu-devel@nongnu.org; Thu, 27 Sep 2012 20:09:31 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:48910) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1THO92-0006v6-1r for qemu-devel@nongnu.org; Thu, 27 Sep 2012 20:09:28 -0400 Received: by pbbrp2 with SMTP id rp2so4341562pbb.4 for ; Thu, 27 Sep 2012 17:09:27 -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=rqRHDl9Wqh0CChCa5YJykaKkLoeLEDRcLW7mWobCqkU=; b=uJFucMJuc4CRnEqWPCKn3VdsI31uTzY0JNaqtke7BaAXFkQ35n6dNY87GyGIF9ZU7b tqkjN5Q7J+f6+/wWkjXQgfAPSUvVnATXpm8KfEnpVdPcpuWoksSuTRXVPHw/prZ+dZw6 qc9feTFofKvZ2bu3n5DzApX80qsri74jq0yEkOEZOX1USxRWJsMOV0bscmr3lOSaVlBx O5+rakI6QyCi/Z18a6//+bKMXgseqoRCPKlyVBP8HlXohuPI2KpPiaLwVXxF9dY7+DUp AdmBfJ2yje7gSlQrTWLp3nERvdtm0FUVvr8pvaic7j32ERlcVR/gn6qeS1CPrY4MSlGB sAYA== Received: by 10.66.88.133 with SMTP id bg5mr8240635pab.80.1348790967446; Thu, 27 Sep 2012 17:09:27 -0700 (PDT) Received: from anchor.twiddle.home.com ([173.160.232.49]) by mx.google.com with ESMTPS id ps2sm4599169pbb.0.2012.09.27.17.09.26 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Sep 2012 17:09:26 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 27 Sep 2012 17:09:23 -0700 Message-Id: <1348790963-25949-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 076/147] target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED 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/cc_helper.c | 9 +- target-s390x/cpu.h | 10 +- target-s390x/fpu_helper.c | 298 +++++++++++++++++---------------------------- target-s390x/helper.h | 31 ++--- target-s390x/insn-data.def | 25 ++++ target-s390x/translate.c | 217 +++++++++++++++++++-------------- 6 files changed, 278 insertions(+), 312 deletions(-) diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c index bead820..27aac03 100644 --- a/target-s390x/cc_helper.c +++ b/target-s390x/cc_helper.c @@ -505,18 +505,15 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, r = cc_calc_sla_64(src, dst); break; - case CC_OP_LTGT_F32: - r = set_cc_f32(env, src, dst); - break; - case CC_OP_LTGT_F64: - r = set_cc_f64(env, src, dst); - break; case CC_OP_NZ_F32: r = set_cc_nz_f32(dst); break; case CC_OP_NZ_F64: r = set_cc_nz_f64(dst); break; + case CC_OP_NZ_F128: + r = set_cc_nz_f128(make_float128(src, dst)); + break; default: cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op)); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index ae9b4a3..7d17bf3 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -471,11 +471,9 @@ enum cc_op { CC_OP_TM_32, /* test under mask (32bit) */ CC_OP_TM_64, /* test under mask (64bit) */ - CC_OP_LTGT_F32, /* FP compare (32bit) */ - CC_OP_LTGT_F64, /* FP compare (64bit) */ - CC_OP_NZ_F32, /* FP dst != 0 (32bit) */ CC_OP_NZ_F64, /* FP dst != 0 (64bit) */ + CC_OP_NZ_F128, /* FP dst != 0 (128bit) */ CC_OP_ICM, /* insert characters under mask */ CC_OP_SLA_32, /* Calculate shift left signed (32bit) */ @@ -517,10 +515,9 @@ static const char *cc_names[] = { [CC_OP_COMP_64] = "CC_OP_COMP_64", [CC_OP_TM_32] = "CC_OP_TM_32", [CC_OP_TM_64] = "CC_OP_TM_64", - [CC_OP_LTGT_F32] = "CC_OP_LTGT_F32", - [CC_OP_LTGT_F64] = "CC_OP_LTGT_F64", [CC_OP_NZ_F32] = "CC_OP_NZ_F32", [CC_OP_NZ_F64] = "CC_OP_NZ_F64", + [CC_OP_NZ_F128] = "CC_OP_NZ_F128", [CC_OP_ICM] = "CC_OP_ICM", [CC_OP_SLA_32] = "CC_OP_SLA_32", [CC_OP_SLA_64] = "CC_OP_SLA_64", @@ -935,10 +932,9 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb) } /* fpu_helper.c */ -uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2); -uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2); uint32_t set_cc_nz_f32(float32 v); uint32_t set_cc_nz_f64(float64 v); +uint32_t set_cc_nz_f128(float128 v); /* misc_helper.c */ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c index ee9420d..debaa7f 100644 --- a/target-s390x/fpu_helper.c +++ b/target-s390x/fpu_helper.c @@ -32,6 +32,52 @@ #define HELPER_LOG(x...) #endif +#define RET128(F) (env->retxl = F.low, F.high) + +#define convert_bit(mask, from, to) \ + (to < from \ + ? (mask / (from / to)) & to \ + : (mask & from) * (to / from)) + +static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr) +{ + /* Install the DXC code. */ + env->fpc = (env->fpc & ~0xff00) | (dxc << 8); + /* Trap. */ + runtime_exception(env, PGM_DATA, retaddr); +} + +/* Should be called after any operation that may raise IEEE exceptions. */ +static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr) +{ + unsigned s390_exc, qemu_exc; + + /* Get the exceptions raised by the current operation. Reset the + fpu_status contents so that the next operation has a clean slate. */ + qemu_exc = env->fpu_status.float_exception_flags; + if (qemu_exc == 0) { + return; + } + env->fpu_status.float_exception_flags = 0; + + /* Convert softfloat exception bits to s390 exception bits. */ + s390_exc = 0; + s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80); + s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40); + s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20); + s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10); + s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08); + + /* Install the exceptions that we raised. */ + env->fpc |= s390_exc << 16; + + /* Send signals for enabled exceptions. */ + s390_exc &= env->fpc >> 24; + if (s390_exc) { + ieee_exception(env, s390_exc, retaddr); + } +} + static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) { switch (float_compare) { @@ -48,19 +94,6 @@ static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) } } -/* condition codes for binary FP ops */ -uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2) -{ - return float_comp_to_cc(env, float32_compare_quiet(v1, v2, - &env->fpu_status)); -} - -uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2) -{ - return float_comp_to_cc(env, float64_compare_quiet(v1, v2, - &env->fpu_status)); -} - /* condition codes for unary FP ops */ uint32_t set_cc_nz_f32(float32 v) { @@ -88,7 +121,7 @@ uint32_t set_cc_nz_f64(float64 v) } } -static uint32_t set_cc_nz_f128(float128 v) +uint32_t set_cc_nz_f128(float128 v) { if (float128_is_any_nan(v)) { return 3; @@ -152,27 +185,31 @@ void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2) env->fregs[f1].l.upper, f1); } -/* 32-bit FP addition RR */ -uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +/* 32-bit FP addition */ +uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) { - env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, - env->fregs[f2].l.upper, - &env->fpu_status); - HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, - env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); - - return set_cc_nz_f32(env->fregs[f1].l.upper); + float32 ret = float32_add(f1, f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return ret; } -/* 64-bit FP addition RR */ -uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +/* 64-bit FP addition */ +uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) { - env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d, - &env->fpu_status); - HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__, - env->fregs[f2].d, env->fregs[f1].d, f1); + float64 ret = float64_add(f1, f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return ret; +} - return set_cc_nz_f64(env->fregs[f1].d); +/* 128-bit FP addition */ +uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, + uint64_t bh, uint64_t bl) +{ + float128 ret = float128_add(make_float128(ah, al), + make_float128(bh, bl), + &env->fpu_status); + handle_exceptions(env, GETPC()); + return RET128(ret); } /* 32-bit FP subtraction RR */ @@ -246,50 +283,51 @@ void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) } /* convert 32-bit float to 64-bit float */ -void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2) +uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) { - env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper, - &env->fpu_status); + float64 ret = float32_to_float64(f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return ret; } /* convert 128-bit float to 64-bit float */ -void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) { - CPU_QuadU x2; - - x2.ll.upper = env->fregs[f2].ll; - x2.ll.lower = env->fregs[f2 + 2].ll; - env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status); - HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d); + float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); + handle_exceptions(env, GETPC()); + return ret; } /* convert 64-bit float to 128-bit float */ -void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) { - CPU_QuadU res; + float128 ret = float64_to_float128(f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return RET128(ret); +} - res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; +/* convert 32-bit float to 128-bit float */ +uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) +{ + float128 ret = float32_to_float128(f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return RET128(ret); } /* convert 64-bit float to 32-bit float */ -void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) { - float64 d2 = env->fregs[f2].d; - - env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status); + float32 ret = float64_to_float32(f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return ret; } /* convert 128-bit float to 32-bit float */ -void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) { - CPU_QuadU x2; - - x2.ll.upper = env->fregs[f2].ll; - x2.ll.lower = env->fregs[f2 + 2].ll; - env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status); - HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper); + float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); + handle_exceptions(env, GETPC()); + return ret; } /* absolute value of 32-bit float */ @@ -328,32 +366,6 @@ uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) return set_cc_nz_f128(v1.q); } -/* load and test 64-bit float */ -uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) -{ - env->fregs[f1].d = env->fregs[f2].d; - return set_cc_nz_f64(env->fregs[f1].d); -} - -/* load and test 32-bit float */ -uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) -{ - env->fregs[f1].l.upper = env->fregs[f2].l.upper; - return set_cc_nz_f32(env->fregs[f1].l.upper); -} - -/* load and test 128-bit float */ -uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) -{ - CPU_QuadU x; - - x.ll.upper = env->fregs[f2].ll; - x.ll.lower = env->fregs[f2 + 2].ll; - env->fregs[f1].ll = x.ll.upper; - env->fregs[f1 + 2].ll = x.ll.lower; - return set_cc_nz_f128(x.q); -} - /* load complement of 32-bit float */ uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { @@ -383,18 +395,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) return set_cc_nz_f128(x1.q); } -/* 32-bit FP addition RM */ -void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val) -{ - float32 v1 = env->fregs[f1].l.upper; - CPU_FloatU v2; - - v2.l = val; - HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__, - v1, f1, v2.f); - env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status); -} - /* 32-bit FP division RM */ void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val) { @@ -419,66 +419,31 @@ void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val) env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status); } -/* 32-bit FP compare RR */ -uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) -{ - float32 v1 = env->fregs[f1].l.upper; - float32 v2 = env->fregs[f2].l.upper; - - HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__, - v1, f1, v2); - return set_cc_f32(env, v1, v2); -} - -/* 64-bit FP compare RR */ -uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) +/* 32-bit FP compare */ +uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) { - float64 v1 = env->fregs[f1].d; - float64 v2 = env->fregs[f2].d; - - HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__, - v1, f1, v2); - return set_cc_f64(env, v1, v2); -} - -/* 128-bit FP compare RR */ -uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - - return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q, - &env->fpu_status)); + int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return float_comp_to_cc(env, cmp); } -/* 64-bit FP compare RM */ -uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) +/* 64-bit FP compare */ +uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) { - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = cpu_ldq_data(env, a2); - HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1, - f1, v2.d); - return set_cc_f64(env, v1, v2.d); + int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); + handle_exceptions(env, GETPC()); + return float_comp_to_cc(env, cmp); } -/* 64-bit FP addition RM */ -uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2) +/* 128-bit FP compare */ +uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, + uint64_t bh, uint64_t bl) { - float64 v1 = env->fregs[f1].d; - CPU_DoubleU v2; - - v2.ll = cpu_ldq_data(env, a2); - HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__, - v1, f1, v2.d); - env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status); - return set_cc_nz_f64(v1); + int cmp = float128_compare_quiet(make_float128(ah, al), + make_float128(bh, bl), + &env->fpu_status); + handle_exceptions(env, GETPC()); + return float_comp_to_cc(env, cmp); } /* 32-bit FP subtraction RM */ @@ -672,23 +637,6 @@ uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) return set_cc_nz_f128(res.q); } -/* 128-bit FP addition RR */ -uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) -{ - CPU_QuadU v1; - CPU_QuadU v2; - CPU_QuadU res; - - v1.ll.upper = env->fregs[f1].ll; - v1.ll.lower = env->fregs[f1 + 2].ll; - v2.ll.upper = env->fregs[f2].ll; - v2.ll.lower = env->fregs[f2 + 2].ll; - res.q = float128_add(v1.q, v2.q, &env->fpu_status); - env->fregs[f1].ll = res.ll.upper; - env->fregs[f1 + 2].ll = res.ll.lower; - return set_cc_nz_f128(res.q); -} - /* 32-bit FP multiplication RR */ void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) { @@ -747,28 +695,6 @@ void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) &env->fpu_status); } -/* convert 32-bit float to 64-bit float */ -void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2) -{ - uint32_t v2; - - v2 = cpu_ldl_data(env, a2); - env->fregs[f1].d = float32_to_float64(v2, - &env->fpu_status); -} - -/* convert 64-bit float to 128-bit float */ -void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) -{ - CPU_DoubleU v2; - CPU_QuadU v1; - - v2.ll = cpu_ldq_data(env, a2); - v1.q = float64_to_float128(v2.d, &env->fpu_status); - env->fregs[f1].ll = v1.ll.upper; - env->fregs[f1 + 2].ll = v1.ll.lower; -} - /* test data class 32-bit */ uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2) { diff --git a/target-s390x/helper.h b/target-s390x/helper.h index c33c844..a2ef6af 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -36,40 +36,36 @@ DEF_HELPER_3(cxfbr, void, env, i32, s32) DEF_HELPER_3(cegbr, void, env, i32, s64) DEF_HELPER_3(cdgbr, void, env, i32, s64) DEF_HELPER_3(cxgbr, void, env, i32, s64) -DEF_HELPER_3(adbr, i32, env, i32, i32) -DEF_HELPER_3(aebr, i32, env, i32, i32) +DEF_HELPER_3(aeb, i64, env, i64, i64) +DEF_HELPER_3(adb, i64, env, i64, i64) +DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64) DEF_HELPER_3(sebr, i32, env, i32, i32) DEF_HELPER_3(sdbr, i32, env, i32, i32) DEF_HELPER_3(debr, void, env, i32, i32) DEF_HELPER_3(dxbr, void, env, i32, i32) DEF_HELPER_3(mdbr, void, env, i32, i32) DEF_HELPER_3(mxbr, void, env, i32, i32) -DEF_HELPER_3(ldebr, void, env, i32, i32) -DEF_HELPER_3(ldxbr, void, env, i32, i32) -DEF_HELPER_3(lxdbr, void, env, i32, i32) -DEF_HELPER_3(ledbr, void, env, i32, i32) -DEF_HELPER_3(lexbr, void, env, i32, i32) +DEF_HELPER_2(ldeb, i64, env, i64) +DEF_HELPER_3(ldxb, i64, env, i64, i64) +DEF_HELPER_2(lxdb, i64, env, i64) +DEF_HELPER_2(lxeb, i64, env, i64) +DEF_HELPER_2(ledb, i64, env, i64) +DEF_HELPER_3(lexb, i64, env, i64, i64) DEF_HELPER_3(lpebr, i32, env, i32, i32) DEF_HELPER_3(lpdbr, i32, env, i32, i32) DEF_HELPER_3(lpxbr, i32, env, i32, i32) -DEF_HELPER_3(ltebr, i32, env, i32, i32) -DEF_HELPER_3(ltdbr, i32, env, i32, i32) -DEF_HELPER_3(ltxbr, i32, env, i32, i32) DEF_HELPER_3(lcebr, i32, env, i32, i32) DEF_HELPER_3(lcdbr, i32, env, i32, i32) DEF_HELPER_3(lcxbr, i32, env, i32, i32) -DEF_HELPER_3(aeb, void, env, i32, i32) DEF_HELPER_3(deb, void, env, i32, i32) DEF_HELPER_3(meeb, void, env, i32, i32) -DEF_HELPER_3(cdb, i32, env, i32, i64) -DEF_HELPER_3(adb, i32, env, i32, i64) DEF_HELPER_3(seb, void, env, i32, i32) DEF_HELPER_3(sdb, i32, env, i32, i64) DEF_HELPER_3(mdb, void, env, i32, i64) DEF_HELPER_3(ddb, void, env, i32, i64) -DEF_HELPER_FLAGS_3(cebr, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(ceb, TCG_CALL_PURE, i32, env, i64, i64) +DEF_HELPER_FLAGS_3(cdb, TCG_CALL_PURE, i32, env, i64, i64) +DEF_HELPER_FLAGS_5(cxb, TCG_CALL_PURE, i32, env, i64, i64, i64, i64) DEF_HELPER_4(cgebr, i32, env, i32, i32, i32) DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32) DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32) @@ -79,7 +75,6 @@ DEF_HELPER_2(lzxr, void, env, i32) DEF_HELPER_4(cfebr, i32, env, i32, i32, i32) DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32) DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32) -DEF_HELPER_3(axbr, i32, env, i32, i32) DEF_HELPER_3(sxbr, i32, env, i32, i32) DEF_HELPER_3(meebr, void, env, i32, i32) DEF_HELPER_3(ddbr, void, env, i32, i32) @@ -87,8 +82,6 @@ DEF_HELPER_4(madb, void, env, i32, i64, i32) DEF_HELPER_4(maebr, void, env, i32, i32, i32) DEF_HELPER_4(madbr, void, env, i32, i32, i32) DEF_HELPER_4(msdbr, void, env, i32, i32, i32) -DEF_HELPER_3(ldeb, void, env, i32, i64) -DEF_HELPER_3(lxdb, void, env, i32, i64) DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64) DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64) DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64) diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def index 8914d34..f1c37e8 100644 --- a/target-s390x/insn-data.def +++ b/target-s390x/insn-data.def @@ -8,6 +8,11 @@ C(0xb9e8, AGRK, RRF_a, DO, r2, r3, r1, 0, add, adds64) C(0xe308, AG, RXY_a, Z, r1, m2_64, r1, 0, add, adds64) C(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64) + C(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32) + C(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64) + C(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128) + C(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32) + C(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64) /* ADD IMMEDIATE */ C(0xc209, AFI, RIL_a, EI, r1, i2, new, r1_32, add, adds32) C(0xeb6a, ASI, SIY, GIE, m1_32s, i2, new, m1_32, add, adds32) @@ -94,6 +99,11 @@ C(0xb930, CGFR, RRE, Z, r1_o, r2_32s, 0, 0, 0, cmps64) C(0xe320, CG, RXY_a, Z, r1_o, m2_64, 0, 0, 0, cmps64) C(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64) + C(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0) + C(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0) + C(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0) + C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0) + C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0) /* COMPARE IMMEDIATE */ C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32) C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64) @@ -239,6 +249,9 @@ C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64) C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64) C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64) + C(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32) + C(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64) + C(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128) /* LOAD BYTE */ C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0) C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0) @@ -303,6 +316,18 @@ C(0xe31e, LRV, RXY_a, Z, 0, m2_32u, new, r1_32, rev32, 0) C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0) +/* LOAD LENGTHENED */ + C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0) + C(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0) + C(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0) + C(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0) + C(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0) + C(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0) +/* LOAD ROUNDED */ + C(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0) + C(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0) + C(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0) + /* LOAD MULTIPLE */ C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0) C(0xeb98, LMY, RSY_a, LD, 0, a2, 0, 0, lm32, 0) diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 739d665..b37c140 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -556,14 +556,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val) gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val); } -static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2) -{ - tcg_gen_extu_i32_i64(cc_src, v1); - tcg_gen_mov_i64(cc_dst, v2); - tcg_gen_discard_i64(cc_vr); - s->cc_op = CC_OP_LTGT_F32; -} - static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1) { gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1); @@ -628,10 +620,9 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_LTUGTU_64: case CC_OP_TM_32: case CC_OP_TM_64: - case CC_OP_LTGT_F32: - case CC_OP_LTGT_F64: case CC_OP_SLA_32: case CC_OP_SLA_64: + case CC_OP_NZ_F128: /* 2 arguments */ gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy); break; @@ -1009,35 +1000,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1, addr = get_address(s, x2, b2, d2); tmp_r1 = tcg_const_i32(r1); switch (op) { - case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */ - potential_page_fault(s); - gen_helper_ldeb(cpu_env, tmp_r1, addr); - break; - case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */ - potential_page_fault(s); - gen_helper_lxdb(cpu_env, tmp_r1, addr); - break; - case 0x9: /* CEB R1,D2(X2,B2) [RXE] */ - tmp = tcg_temp_new_i64(); - tmp32 = load_freg32(r1); - tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s)); - set_cc_cmp_f32_i64(s, tmp32, tmp); - tcg_temp_free_i64(tmp); - tcg_temp_free_i32(tmp32); - break; - case 0xa: /* AEB R1,D2(X2,B2) [RXE] */ - tmp = tcg_temp_new_i64(); - tmp32 = tcg_temp_new_i32(); - tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s)); - tcg_gen_trunc_i64_i32(tmp32, tmp); - gen_helper_aeb(cpu_env, tmp_r1, tmp32); - tcg_temp_free_i64(tmp); - tcg_temp_free_i32(tmp32); - - tmp32 = load_freg32(r1); - gen_set_cc_nz_f32(s, tmp32); - tcg_temp_free_i32(tmp32); - break; case 0xb: /* SEB R1,D2(X2,B2) [RXE] */ tmp = tcg_temp_new_i64(); tmp32 = tcg_temp_new_i32(); @@ -1084,16 +1046,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1, tcg_temp_free_i64(tmp); tcg_temp_free_i32(tmp32); break; - case 0x19: /* CDB R1,D2(X2,B2) [RXE] */ - potential_page_fault(s); - gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr); - set_cc_static(s); - break; - case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */ - potential_page_fault(s); - gen_helper_adb(cc_op, cpu_env, tmp_r1, addr); - set_cc_static(s); - break; case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr); @@ -1524,24 +1476,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3, case 0x0: /* LPEBR R1,R2 [RRE] */ FP_HELPER_CC(lpebr); break; - case 0x2: /* LTEBR R1,R2 [RRE] */ - FP_HELPER_CC(ltebr); - break; case 0x3: /* LCEBR R1,R2 [RRE] */ FP_HELPER_CC(lcebr); break; - case 0x4: /* LDEBR R1,R2 [RRE] */ - FP_HELPER(ldebr); - break; - case 0x5: /* LXDBR R1,R2 [RRE] */ - FP_HELPER(lxdbr); - break; - case 0x9: /* CEBR R1,R2 [RRE] */ - FP_HELPER_CC(cebr); - break; - case 0xa: /* AEBR R1,R2 [RRE] */ - FP_HELPER_CC(aebr); - break; case 0xb: /* SEBR R1,R2 [RRE] */ FP_HELPER_CC(sebr); break; @@ -1551,9 +1488,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3, case 0x10: /* LPDBR R1,R2 [RRE] */ FP_HELPER_CC(lpdbr); break; - case 0x12: /* LTDBR R1,R2 [RRE] */ - FP_HELPER_CC(ltdbr); - break; case 0x13: /* LCDBR R1,R2 [RRE] */ FP_HELPER_CC(lcdbr); break; @@ -1563,12 +1497,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3, case 0x17: /* MEEBR R1,R2 [RRE] */ FP_HELPER(meebr); break; - case 0x19: /* CDBR R1,R2 [RRE] */ - FP_HELPER_CC(cdbr); - break; - case 0x1a: /* ADBR R1,R2 [RRE] */ - FP_HELPER_CC(adbr); - break; case 0x1b: /* SDBR R1,R2 [RRE] */ FP_HELPER_CC(sdbr); break; @@ -1605,27 +1533,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3, case 0x40: /* LPXBR R1,R2 [RRE] */ FP_HELPER_CC(lpxbr); break; - case 0x42: /* LTXBR R1,R2 [RRE] */ - FP_HELPER_CC(ltxbr); - break; case 0x43: /* LCXBR R1,R2 [RRE] */ FP_HELPER_CC(lcxbr); break; - case 0x44: /* LEDBR R1,R2 [RRE] */ - FP_HELPER(ledbr); - break; - case 0x45: /* LDXBR R1,R2 [RRE] */ - FP_HELPER(ldxbr); - break; - case 0x46: /* LEXBR R1,R2 [RRE] */ - FP_HELPER(lexbr); - break; - case 0x49: /* CXBR R1,R2 [RRE] */ - FP_HELPER_CC(cxbr); - break; - case 0x4a: /* AXBR R1,R2 [RRE] */ - FP_HELPER_CC(axbr); - break; case 0x4b: /* SXBR R1,R2 [RRE] */ FP_HELPER_CC(sxbr); break; @@ -2260,6 +2170,25 @@ static ExitStatus op_addc(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_aeb(DisasContext *s, DisasOps *o) +{ + gen_helper_aeb(o->out, cpu_env, o->in1, o->in2); + return NO_EXIT; +} + +static ExitStatus op_adb(DisasContext *s, DisasOps *o) +{ + gen_helper_adb(o->out, cpu_env, o->in1, o->in2); + return NO_EXIT; +} + +static ExitStatus op_axb(DisasContext *s, DisasOps *o) +{ + gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2); + return_low128(o->out2); + return NO_EXIT; +} + static ExitStatus op_and(DisasContext *s, DisasOps *o) { tcg_gen_and_i64(o->out, o->in1, o->in2); @@ -2354,6 +2283,27 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o) return help_branch(s, &c, is_imm, imm, o->in2); } +static ExitStatus op_ceb(DisasContext *s, DisasOps *o) +{ + gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2); + set_cc_static(s); + return NO_EXIT; +} + +static ExitStatus op_cdb(DisasContext *s, DisasOps *o) +{ + gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2); + set_cc_static(s); + return NO_EXIT; +} + +static ExitStatus op_cxb(DisasContext *s, DisasOps *o) +{ + gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2); + set_cc_static(s); + return NO_EXIT; +} + static ExitStatus op_clc(DisasContext *s, DisasOps *o) { int l = get_field(s->fields, l1); @@ -2610,6 +2560,44 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o) return NO_EXIT; } +static ExitStatus op_ldeb(DisasContext *s, DisasOps *o) +{ + gen_helper_ldeb(o->out, cpu_env, o->in2); + return NO_EXIT; +} + +static ExitStatus op_ledb(DisasContext *s, DisasOps *o) +{ + gen_helper_ledb(o->out, cpu_env, o->in2); + return NO_EXIT; +} + +static ExitStatus op_ldxb(DisasContext *s, DisasOps *o) +{ + gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2); + return NO_EXIT; +} + +static ExitStatus op_lexb(DisasContext *s, DisasOps *o) +{ + gen_helper_lexb(o->out, cpu_env, o->in1, o->in2); + return NO_EXIT; +} + +static ExitStatus op_lxdb(DisasContext *s, DisasOps *o) +{ + gen_helper_lxdb(o->out, cpu_env, o->in2); + return_low128(o->out2); + return NO_EXIT; +} + +static ExitStatus op_lxeb(DisasContext *s, DisasOps *o) +{ + gen_helper_lxeb(o->out, cpu_env, o->in2); + return_low128(o->out2); + return NO_EXIT; +} + static ExitStatus op_llgt(DisasContext *s, DisasOps *o) { tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff); @@ -3369,6 +3357,21 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o) gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2); } +static void cout_f32(DisasContext *s, DisasOps *o) +{ + gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out); +} + +static void cout_f64(DisasContext *s, DisasOps *o) +{ + gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out); +} + +static void cout_f128(DisasContext *s, DisasOps *o) +{ + gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2); +} + static void cout_nabs32(DisasContext *s, DisasOps *o) { gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out); @@ -3482,6 +3485,21 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o) o->g_out = o->g_out2 = true; } +static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o) +{ + o->out = fregs[get_field(f, r1)]; + o->g_out = true; +} + +static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o) +{ + /* ??? Specification exception: r1 must be < 14. */ + int r1 = get_field(f, r1); + o->out = fregs[r1]; + o->out2 = fregs[(r1 + 2) & 15]; + o->g_out = o->g_out2 = true; +} + /* ====================================================================== */ /* The "Write OUTput" generators. These generally perform some non-trivial copy of data to TCG globals, or to main memory. The trivial cases are @@ -3539,6 +3557,7 @@ static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o) static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o) { + /* ??? Specification exception: r1 must be < 14. */ int f1 = get_field(s->fields, r1); store_freg(f1, o->out); store_freg((f1 + 2) & 15, o->out2); @@ -3685,6 +3704,15 @@ static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o) o->g_in1 = true; } +static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o) +{ + /* ??? Specification exception: r1 must be < 14. */ + int r1 = get_field(f, r1); + o->out = fregs[r1]; + o->out2 = fregs[(r1 + 2) & 15]; + o->g_out = o->g_out2 = true; +} + static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o) { o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1)); @@ -3832,9 +3860,10 @@ static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o) static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o) { - int f2 = get_field(f, r2); - o->in1 = fregs[f2]; - o->in2 = fregs[(f2 + 2) & 15]; + /* ??? Specification exception: r1 must be < 14. */ + int r2 = get_field(f, r2); + o->in1 = fregs[r2]; + o->in2 = fregs[(r2 + 2) & 15]; o->g_in1 = o->g_in2 = true; }