From patchwork Thu Jan 4 01:29:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 855333 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zBrBn2QStz9s7n for ; Thu, 4 Jan 2018 12:42:09 +1100 (AEDT) Received: from localhost ([::1]:44785 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eWuXn-0001KL-Bx for incoming@patchwork.ozlabs.org; Wed, 03 Jan 2018 20:42:07 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58353) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eWuLT-0000q5-3f for qemu-devel@nongnu.org; Wed, 03 Jan 2018 20:29:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eWuLR-00078O-FI for qemu-devel@nongnu.org; Wed, 03 Jan 2018 20:29:23 -0500 Received: from mout.kundenserver.de ([217.72.192.75]:65127) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eWuLR-000778-4C for qemu-devel@nongnu.org; Wed, 03 Jan 2018 20:29:21 -0500 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue105 [212.227.15.183]) with ESMTPSA (Nemesis) id 0M7sQq-1esr543TEG-00vPuU; Thu, 04 Jan 2018 02:29:19 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Thu, 4 Jan 2018 02:29:03 +0100 Message-Id: <20180104012913.30763-8-laurent@vivier.eu> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180104012913.30763-1-laurent@vivier.eu> References: <20180104012913.30763-1-laurent@vivier.eu> X-Provags-ID: V03:K0:qnYVp/HxAkMlnzbAFMx0UshjLQ/WmsNVeCS147ex+AH12vT//yh WHF/TdyK0vwRmquFX1rHrae+h3SyvfDROBo7vC9hkA4vtW+3PtMvc/F6tStdzjINDL3CDB+ 8QMLRDlilwGLNLdey+1+7hu/uM8/nVA8gvCDKvPXwFsXqZ05/XkUeFQA6rafwXbkQqKkkg6 At0hUJjChuP29icrkbn5w== X-UI-Out-Filterresults: notjunk:1; V01:K0:4sUfuyoQOTs=:4oVHR/HhADH7A/faq3/y7j oo1naIYvgB/Gn57M54A6n6Xu6prjAO343PXhXk8wA7B+giSnRm+uBplixDU8ZDu2mkh0m8T0F L6he8lAtwsXpcy0sAmDN3VuhzvAWc4Mqs6luB3pxozuycD4+iXo8/y1U2SMhIxs43NysnWu6e 3NDlPWVk4TtHE9qBmlfQxaka5v7Kk19E6cyzQnqqhWvBfxDR173SdmYoI6D5SjT5zMB6RYShA 4OwncU2V356rFOTQGUIUMyAOyWDV9LLUTf/UKuyqOQveHh4K95LIX4tHhD793U46ByIthBPjj xr9Qe0tjAtL6sHFHJ3K4hQNt+9Qz4AyTx9i4HhLwIbSiyZOvE6WBiTEJ8WfaGTeGA4WpzECm4 7+1mhYbMbG4FaRfdtwj3gQWSBXVVkXnMHoQ6c9Q9LyDMsBS1EzE1SCxCJQBt1xeF5O3XyOVW/ w86ol34gJWHjqVDH2459xrhOS5tIyS6gMMl6/MnblKjnDbTWKwCar1LMqcIX8Yt0qCEYQc3iT Skgj3/BiFyRnupOeRsPCxwuA4BhEbALlsJ+lZEOhIqpdgScmjtz7SNRVrMv/diWPxkmnRN/6f hFBcYqx5QMQpHNeInu4Weu11T417i1s4fCmvChiDUtqGkloJNFWdMmkzHeffLGEePtd4qhDEn uGE/ZwR2PaqiF5DJMmrcndA9AC/9Ox3AO7CzVJMixltrFFPxpgGyX524fnkM2BkDQMAseIZDf +Hz4MSlHueruukBpfbgPShDosRStZ+NVyQjjIQ== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.75 Subject: [Qemu-devel] [PATCH v7 07/17] target/m68k: add chk and chk2 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: Thomas Huth , Richard Henderson , Laurent Vivier Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" chk and chk2 compare a value to boundaries, and trigger a CHK exception if the value is out of bounds. Signed-off-by: Laurent Vivier Suggested-by: Richard Henderson Reviewed-by: Richard Henderson --- Notes: v7: chk: always update C and N flags add some comments move flush_flags() from the helper to the code generator, because otherwise we need to do an update_cc_op() before calling the helper to be sure env->cc_op and s->cc_op are synchronized v6: use helpers as suggested by Richard linux-user/main.c | 7 +++++ target/m68k/cpu.c | 2 ++ target/m68k/cpu.h | 1 + target/m68k/helper.h | 3 ++ target/m68k/op_helper.c | 61 +++++++++++++++++++++++++++++++++++++++ target/m68k/translate.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 150 insertions(+), 1 deletion(-) diff --git a/linux-user/main.c b/linux-user/main.c index 71696ed33d..99a551b04f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2985,6 +2985,13 @@ void cpu_loop(CPUM68KState *env) info._sifields._sigfault._addr = env->pc; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; + case EXCP_CHK: + info.si_signo = TARGET_SIGFPE; + info.si_errno = 0; + info.si_code = TARGET_FPE_INTOVF; + info._sifields._sigfault._addr = env->pc; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + break; case EXCP_DIV0: info.si_signo = TARGET_SIGFPE; info.si_errno = 0; diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 0a3dd83548..57ffcb2114 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -134,6 +134,7 @@ static void m68020_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_CAS); m68k_set_feature(env, M68K_FEATURE_BKPT); m68k_set_feature(env, M68K_FEATURE_RTD); + m68k_set_feature(env, M68K_FEATURE_CHK2); } #define m68030_cpu_initfn m68020_cpu_initfn #define m68040_cpu_initfn m68020_cpu_initfn @@ -156,6 +157,7 @@ static void m68060_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_CAS); m68k_set_feature(env, M68K_FEATURE_BKPT); m68k_set_feature(env, M68K_FEATURE_RTD); + m68k_set_feature(env, M68K_FEATURE_CHK2); } static void m5208_cpu_initfn(Object *obj) diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index cd4b3a7c7b..68396bdd70 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -305,6 +305,7 @@ enum m68k_features { M68K_FEATURE_CAS, M68K_FEATURE_BKPT, M68K_FEATURE_RTD, + M68K_FEATURE_CHK2, }; static inline int m68k_feature(CPUM68KState *env, int feature) diff --git a/target/m68k/helper.h b/target/m68k/helper.h index eebe52dae5..78483da003 100644 --- a/target/m68k/helper.h +++ b/target/m68k/helper.h @@ -94,3 +94,6 @@ DEF_HELPER_FLAGS_4(bfchg_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32) DEF_HELPER_FLAGS_4(bfclr_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32) DEF_HELPER_FLAGS_4(bfset_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32) DEF_HELPER_FLAGS_4(bfffo_mem, TCG_CALL_NO_WG, i64, env, i32, s32, i32) + +DEF_HELPER_3(chk, void, env, s32, s32) +DEF_HELPER_4(chk2, void, env, s32, s32, s32) diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 5c7b27b9ca..06144d436d 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -947,3 +947,64 @@ uint64_t HELPER(bfffo_mem)(CPUM68KState *env, uint32_t addr, is already zero. */ return n | ffo; } + +void HELPER(chk)(CPUM68KState *env, int32_t val, int32_t ub) +{ + /* From the specs: + * X: Not affected, C,V,Z: Undefined, + * N: Set if val < 0; cleared if val > ub, undefined otherwise + * We implement here values found from a real MC68040: + * X,V,Z: Not affected + * N: Set if val < 0; cleared if val >= 0 + * C: if 0 <= ub: set if val < 0 or val > ub, cleared otherwise + * if 0 > ub: set if val > ub and val < 0, cleared otherwise + */ + env->cc_n = val; + env->cc_c = 0 <= ub ? val < 0 || val > ub : val > ub && val < 0; + + if (val < 0 || val > ub) { + CPUState *cs = CPU(m68k_env_get_cpu(env)); + + /* Recover PC and CC_OP for the beginning of the insn. */ + cpu_restore_state(cs, GETPC()); + + /* flags have been modified by gen_flush_flags() */ + env->cc_op = CC_OP_FLAGS; + /* Adjust PC to end of the insn. */ + env->pc += 2; + + cs->exception_index = EXCP_CHK; + cpu_loop_exit(cs); + } +} + +void HELPER(chk2)(CPUM68KState *env, int32_t val, int32_t lb, int32_t ub) +{ + /* From the specs: + * X: Not affected, N,V: Undefined, + * Z: Set if val is equal to lb or ub + * V: Set if val < lb or val > ub, cleared otherwise + * We implement here values found from a real MC68040: + * X,N,V: Not affected + * Z: Set if val is equal to lb or ub + * C: if lb <= ub: set if val < lb or val > ub, cleared otherwise + * if lb > ub: set if val > ub and val < lb, cleared otherwise + */ + env->cc_z = val != lb && val != ub; + env->cc_c = lb <= ub ? val < lb || val > ub : val > ub && val < lb; + + if (env->cc_c) { + CPUState *cs = CPU(m68k_env_get_cpu(env)); + + /* Recover PC and CC_OP for the beginning of the insn. */ + cpu_restore_state(cs, GETPC()); + + /* flags have been modified by gen_flush_flags() */ + env->cc_op = CC_OP_FLAGS; + /* Adjust PC to end of the insn. */ + env->pc += 4; + + cs->exception_index = EXCP_CHK; + cpu_loop_exit(cs); + } +} diff --git a/target/m68k/translate.c b/target/m68k/translate.c index a1e424e3db..7f52065375 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4203,6 +4203,80 @@ DISAS_INSN(ff1) gen_helper_ff1(reg, reg); } +DISAS_INSN(chk) +{ + TCGv src, reg; + int opsize; + + switch ((insn >> 7) & 3) { + case 3: + opsize = OS_WORD; + break; + case 2: + if (m68k_feature(env, M68K_FEATURE_CHK2)) { + opsize = OS_LONG; + break; + } + /* fallthru */ + default: + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + SRC_EA(env, src, opsize, 1, NULL); + reg = gen_extend(DREG(insn, 9), opsize, 1); + + gen_flush_flags(s); + gen_helper_chk(cpu_env, reg, src); +} + +DISAS_INSN(chk2) +{ + uint16_t ext; + TCGv addr1, addr2, bound1, bound2, reg; + int opsize; + + switch ((insn >> 9) & 3) { + case 0: + opsize = OS_BYTE; + break; + case 1: + opsize = OS_WORD; + break; + case 2: + opsize = OS_LONG; + break; + default: + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + + ext = read_im16(env, s); + if ((ext & 0x0800) == 0) { + gen_exception(s, s->insn_pc, EXCP_ILLEGAL); + return; + } + + addr1 = gen_lea(env, s, insn, OS_UNSIZED); + addr2 = tcg_temp_new(); + tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize)); + + bound1 = gen_load(s, opsize, addr1, 1); + tcg_temp_free(addr1); + bound2 = gen_load(s, opsize, addr2, 1); + tcg_temp_free(addr2); + + reg = tcg_temp_new(); + if (ext & 0x8000) { + tcg_gen_mov_i32(reg, AREG(ext, 12)); + } else { + gen_ext(reg, DREG(ext, 12), opsize, 1); + } + + gen_flush_flags(s); + gen_helper_chk2(cpu_env, reg, bound1, bound2); + tcg_temp_free(reg); +} + static TCGv gen_get_sr(DisasContext *s) { TCGv ccr; @@ -5306,7 +5380,7 @@ void register_m68k_insns (CPUM68KState *env) BASE(undef, 0000, 0000); INSN(arith_im, 0080, fff8, CF_ISA_A); INSN(arith_im, 0000, ff00, M68000); - INSN(undef, 00c0, ffc0, M68000); + INSN(chk2, 00c0, f9c0, CHK2); INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC); BASE(bitop_reg, 0100, f1c0); BASE(bitop_reg, 0140, f1c0); @@ -5339,6 +5413,7 @@ void register_m68k_insns (CPUM68KState *env) BASE(move, 1000, f000); BASE(move, 2000, f000); BASE(move, 3000, f000); + INSN(chk, 4000, f040, M68000); INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); INSN(negx, 4080, fff8, CF_ISA_A); INSN(negx, 4000, ff00, M68000);