From patchwork Thu Oct 27 00:42:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 9398763 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 0643E60234 for ; Thu, 27 Oct 2016 00:48:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C12C029E4C for ; Thu, 27 Oct 2016 00:48:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B431429E57; Thu, 27 Oct 2016 00:48:12 +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.4 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM 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 C624529E4C for ; Thu, 27 Oct 2016 00:48:11 +0000 (UTC) Received: from localhost ([::1]:38235 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzYra-00052g-Lt for patchwork-qemu-devel@patchwork.kernel.org; Wed, 26 Oct 2016 20:48:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57244) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzYmc-0001Ft-4u for qemu-devel@nongnu.org; Wed, 26 Oct 2016 20:43:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bzYmY-0000vy-Pm for qemu-devel@nongnu.org; Wed, 26 Oct 2016 20:43:02 -0400 Received: from mout.kundenserver.de ([212.227.126.187]:56423) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1bzYmY-0000uj-F1 for qemu-devel@nongnu.org; Wed, 26 Oct 2016 20:42:58 -0400 Received: from Quad.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue005) with ESMTPSA (Nemesis) id 0LroEc-1d369L3KiE-013cvu; Thu, 27 Oct 2016 02:42:38 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Thu, 27 Oct 2016 02:42:19 +0200 Message-Id: <1477528950-8115-7-git-send-email-laurent@vivier.eu> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1477528950-8115-1-git-send-email-laurent@vivier.eu> References: <1477528950-8115-1-git-send-email-laurent@vivier.eu> X-Provags-ID: V03:K0:mKvyD/x+h+68FNdqyXnNjEoZXELetjYRnEjAqowOnO6byjyYKpO 2QL1qpQWI6jjnHdBfY3je2yrl9qzdLw/VEUT7affo+vexzr3ykGgQIVf9BO2L0LY1phRzys pkDpNWU7WiI8PiGQbv4PIcBXpPd41na3GPC8zWECzb/ajRNKveJC5vDQ6g+jEXtuCwN1x+H CR6QSvc4LxvocnZlLEnHQ== X-UI-Out-Filterresults: notjunk:1; V01:K0:pq6C7z4dxT0=:ljJAjU2A5LZN8F6nC0fO71 YaLY82DqtCPZLeSg+rxLDkqNBWLVav4fBdveTNzJfukbq+MYGgOE8EokspkvrD7dq+dGL+d9w CRpQumLVcMqMUX61QmnEWXhqZ9ojlZfF51DiIgnUmZ/40MHveDZdMySjQ1R3qYe+wNo3ZY5dJ PU+Q4Tq4QpQ0AmRmbbKfEPA4SHKdY1Foo4uUJ3PVHIX4UaF3Sn//SnTkY6zuQfFVKScAcnR5f gqlCBTkQGg/smKIM3+Vx68qzVaN5dA65tHz6WWO3n0GIZLq7rihTNJxWseX++mhD/m0MfCgjI +5EbuAah/TTh/cORf5N2IaiUgg3WsgJAVU0SVxLY7l2ZRDOpBDCwzQKlzbt6GeKbKs6IAFzin 1fip8YSvkSbdbbeaUT9BkOqJCaLpUFivfQKdwWalcltNtztnE+26k8GwBFkPjHI2LY0bT0IK1 86w2hqK1Q7c+UxFi8rKxEbgkScT7cOX6ZUfoNwefHsa5xmLmmiDi4GB9wPGYpV1y+vzlOsP3m 0u0Cb59wvKmf1/rAuPsYMHVi05T6rw92T6y80W6g/A5WUsFMSZIOPx75JNl752nzlky2jFZZg gETTi92qbI0TrXcxMi3BD1MXdKUPYBfHji97RHIP3yVBMc2uGNZW2/lvkUiqhisM6BtD87/qX 0XkZsSYUuoz13iyn86e9yZJl5Cqu0v3aO9UbiT8C8aD8ODFmXJ8575aW98IaeO32maSc= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 212.227.126.187 Subject: [Qemu-devel] [PATCH v2 06/17] target-m68k: Inline addx, subx, negx 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: Laurent Vivier , gerg@uclinux.org, schwab@linux-m68k.org, agraf@suse.de, Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Richard Henderson Signed-off-by: Richard Henderson And add opcodes for 680x0 Signed-off-by: Laurent Vivier --- target-m68k/helper.c | 40 ---------- target-m68k/helper.h | 2 - target-m68k/translate.c | 196 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 178 insertions(+), 60 deletions(-) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 094a7e5..e838638 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -277,46 +277,6 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v) return val; } -uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2) -{ - uint32_t res, new_x; - - if (env->cc_x) { - new_x = (op1 <= op2); - res = op1 - (op2 + 1); - } else { - new_x = (op1 < op2); - res = op1 - op2; - } - env->cc_x = new_x; - env->cc_c = new_x; - env->cc_n = res; - env->cc_z |= res; /* !Z is sticky */ - env->cc_v = (res ^ op1) & (op1 ^ op2); - - return res; -} - -uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2) -{ - uint32_t res, new_x; - - if (env->cc_x) { - res = op1 + op2 + 1; - new_x = (res <= op2); - } else { - res = op1 + op2; - new_x = (res < op2); - } - env->cc_x = new_x; - env->cc_c = new_x; - env->cc_n = res; - env->cc_z |= res; /* !Z is sticky. */ - env->cc_v = (res ^ op1) & ~(op1 ^ op2); - - return res; -} - void HELPER(set_sr)(CPUM68KState *env, uint32_t val) { env->sr = val & 0xffe0; diff --git a/target-m68k/helper.h b/target-m68k/helper.h index c868148..2697e32 100644 --- a/target-m68k/helper.h +++ b/target-m68k/helper.h @@ -3,8 +3,6 @@ DEF_HELPER_1(ff1, i32, i32) DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_2(divu, void, env, i32) DEF_HELPER_2(divs, void, env, i32) -DEF_HELPER_3(addx_cc, i32, env, i32, i32) -DEF_HELPER_3(subx_cc, i32, env, i32, i32) DEF_HELPER_3(shl_cc, i32, env, i32, i32) DEF_HELPER_3(shr_cc, i32, env, i32, i32) DEF_HELPER_3(sar_cc, i32, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 1836a22..fd6631d 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1536,11 +1536,44 @@ DISAS_INSN(move) DISAS_INSN(negx) { - TCGv reg; + TCGv z; + TCGv src; + TCGv addr; + int opsize; - gen_flush_flags(s); - reg = DREG(insn, 0); - gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg); + opsize = insn_opsize(insn); + SRC_EA(env, src, opsize, 1, &addr); + + gen_flush_flags(s); /* compute old Z */ + + /* Perform substract with borrow. + * (X, N) = -(src + X); + */ + + z = tcg_const_i32(0); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z); + tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X); + tcg_temp_free(z); + gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); + + tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1); + + /* Compute signed-overflow for negation. The normal formula for + * subtraction is (res ^ src) & (src ^ dest), but with dest==0 + * this simplies to res & src. + */ + + tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src); + + /* Copy the rest of the results into place. */ + tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); + + set_cc_op(s, CC_OP_FLAGS); + + /* result is in QREG_CC_N */ + + DEST_EA(env, insn, opsize, QREG_CC_N, &addr); } DISAS_INSN(lea) @@ -1975,15 +2008,75 @@ DISAS_INSN(suba) tcg_gen_sub_i32(reg, reg, src); } -DISAS_INSN(subx) +static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize) { - TCGv reg; + TCGv tmp; + + gen_flush_flags(s); /* compute old Z */ + + /* Perform substract with borrow. + * (X, N) = dest - (src + X); + */ + + tmp = tcg_const_i32(0); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, tmp, QREG_CC_X, tmp); + tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, dest, tmp, QREG_CC_N, QREG_CC_X); + gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); + tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1); + + /* Compute signed-overflow for substract. */ + + tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, dest); + tcg_gen_xor_i32(tmp, dest, src); + tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, tmp); + tcg_temp_free(tmp); + + /* Copy the rest of the results into place. */ + tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); + + set_cc_op(s, CC_OP_FLAGS); + + /* result is in QREG_CC_N */ +} + +DISAS_INSN(subx_reg) +{ + TCGv dest; TCGv src; + int opsize; - gen_flush_flags(s); - reg = DREG(insn, 9); - src = DREG(insn, 0); - gen_helper_subx_cc(reg, cpu_env, reg, src); + opsize = insn_opsize(insn); + + src = gen_extend(DREG(insn, 0), opsize, 1); + dest = gen_extend(DREG(insn, 9), opsize, 1); + + gen_subx(s, src, dest, opsize); + + gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N); +} + +DISAS_INSN(subx_mem) +{ + TCGv src; + TCGv addr_src; + TCGv dest; + TCGv addr_dest; + int opsize; + + opsize = insn_opsize(insn); + + addr_src = AREG(insn, 0); + tcg_gen_subi_i32(addr_src, addr_src, opsize); + src = gen_load(s, opsize, addr_src, 1); + + addr_dest = AREG(insn, 9); + tcg_gen_subi_i32(addr_dest, addr_dest, opsize); + dest = gen_load(s, opsize, addr_dest, 1); + + gen_subx(s, src, dest, opsize); + + gen_store(s, opsize, addr_dest, QREG_CC_N); } DISAS_INSN(mov3q) @@ -2102,15 +2195,74 @@ DISAS_INSN(adda) tcg_gen_add_i32(reg, reg, src); } -DISAS_INSN(addx) +static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize) { - TCGv reg; + TCGv tmp; + + gen_flush_flags(s); /* compute old Z */ + + /* Perform addition with carry. + * (X, N) = src + dest + X; + */ + + tmp = tcg_const_i32(0); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, tmp, dest, tmp); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, tmp); + gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1); + + /* Compute signed-overflow for addition. */ + + tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src); + tcg_gen_xor_i32(tmp, dest, src); + tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, tmp); + tcg_temp_free(tmp); + + /* Copy the rest of the results into place. */ + tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); + + set_cc_op(s, CC_OP_FLAGS); + + /* result is in QREG_CC_N */ +} + +DISAS_INSN(addx_reg) +{ + TCGv dest; TCGv src; + int opsize; - gen_flush_flags(s); - reg = DREG(insn, 9); - src = DREG(insn, 0); - gen_helper_addx_cc(reg, cpu_env, reg, src); + opsize = insn_opsize(insn); + + dest = gen_extend(DREG(insn, 9), opsize, 1); + src = gen_extend(DREG(insn, 0), opsize, 1); + + gen_addx(s, src, dest, opsize); + + gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N); +} + +DISAS_INSN(addx_mem) +{ + TCGv src; + TCGv addr_src; + TCGv dest; + TCGv addr_dest; + int opsize; + + opsize = insn_opsize(insn); + + addr_src = AREG(insn, 0); + tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize)); + src = gen_load(s, opsize, addr_src, 1); + + addr_dest = AREG(insn, 9); + tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize)); + dest = gen_load(s, opsize, addr_dest, 1); + + gen_addx(s, src, dest, opsize); + + gen_store(s, opsize, addr_dest, QREG_CC_N); } /* TODO: This could be implemented without helper functions. */ @@ -3109,6 +3261,8 @@ void register_m68k_insns (CPUM68KState *env) BASE(move, 3000, f000); INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); INSN(negx, 4080, fff8, CF_ISA_A); + INSN(negx, 4000, ff00, M68000); + INSN(undef, 40c0, ffc0, M68000); INSN(move_from_sr, 40c0, fff8, CF_ISA_A); INSN(move_from_sr, 40c0, ffc0, M68000); BASE(lea, 41c0, f1c0); @@ -3179,7 +3333,10 @@ void register_m68k_insns (CPUM68KState *env) BASE(or, 8000, f000); BASE(divw, 80c0, f0c0); BASE(addsub, 9000, f000); - INSN(subx, 9180, f1f8, CF_ISA_A); + INSN(undef, 90c0, f0c0, CF_ISA_A); + INSN(subx_reg, 9180, f1f8, CF_ISA_A); + INSN(subx_reg, 9100, f138, M68000); + INSN(subx_mem, 9108, f138, M68000); INSN(suba, 91c0, f1c0, CF_ISA_A); BASE(undef_mac, a000, f000); @@ -3211,7 +3368,10 @@ void register_m68k_insns (CPUM68KState *env) INSN(exg_da, c188, f1f8, M68000); BASE(mulw, c0c0, f0c0); BASE(addsub, d000, f000); - INSN(addx, d180, f1f8, CF_ISA_A); + INSN(undef, d0c0, f0c0, CF_ISA_A); + INSN(addx_reg, d180, f1f8, CF_ISA_A); + INSN(addx_reg, d100, f138, M68000); + INSN(addx_mem, d108, f138, M68000); INSN(adda, d1c0, f1c0, CF_ISA_A); INSN(adda, d0c0, f0c0, M68000); INSN(shift_im, e080, f0f0, CF_ISA_A);