From patchwork Wed May 4 20:12:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 9018671 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E9906BF29F for ; Wed, 4 May 2016 20:29:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F375720382 for ; Wed, 4 May 2016 20:29:40 +0000 (UTC) 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.kernel.org (Postfix) with ESMTPS id E2595201EC for ; Wed, 4 May 2016 20:29:39 +0000 (UTC) Received: from localhost ([::1]:50144 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ay3QO-0006Ra-37 for patchwork-qemu-devel@patchwork.kernel.org; Wed, 04 May 2016 16:29:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47757) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ay3DN-0004k8-TL for qemu-devel@nongnu.org; Wed, 04 May 2016 16:16:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ay3DB-0004gR-SL for qemu-devel@nongnu.org; Wed, 04 May 2016 16:16:04 -0400 Received: from smtp1-g21.free.fr ([2a01:e0c:1:1599::10]:22296) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ay3DB-0004YV-GL for qemu-devel@nongnu.org; Wed, 04 May 2016 16:15:57 -0400 Received: from Quad.localdomain (unknown [IPv6:2a01:e34:eeee:5240:12c3:7bff:fe6b:9a76]) by smtp1-g21.free.fr (Postfix) with ESMTPS id 82F79B004D9; Wed, 4 May 2016 20:09:19 +0200 (CEST) From: Laurent Vivier To: qemu-devel@nongnu.org Date: Wed, 4 May 2016 22:12:08 +0200 Message-Id: <1462392752-17703-29-git-send-email-laurent@vivier.eu> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1462392752-17703-1-git-send-email-laurent@vivier.eu> References: <1462392752-17703-1-git-send-email-laurent@vivier.eu> X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 2a01:e0c:1:1599::10 Subject: [Qemu-devel] [PATCH 28/52] target-m68k: add addx/subx/negx ops 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 , rth@twiddle.net, schwab@linux-m68k.org, agraf@suse.de, gerg@uclinux.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Laurent Vivier --- target-m68k/translate.c | 200 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 160 insertions(+), 40 deletions(-) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 13ae953..5914185 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1503,27 +1503,46 @@ DISAS_INSN(move) DISAS_INSN(negx) { - TCGv reg, z; + TCGv z; + TCGv src; + TCGv addr; + int opsize; - reg = DREG(insn, 0); + 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); + */ - /* Perform subtraction with borrow. */ z = tcg_const_i32(0); - tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_X, z); + 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 ^ src1) & (src1 ^ src2), but with src1==0 - this simplies to res & src2. */ - tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, reg); + * 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_mov_i32(QREG_CC_Z, QREG_CC_N); + tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ + gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0); + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); - tcg_gen_mov_i32(reg, QREG_CC_N); + 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) @@ -1943,32 +1962,78 @@ 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, src, z; + TCGv tmp; - reg = DREG(insn, 9); - src = DREG(insn, 0); + gen_flush_flags(s); /* compute old Z */ - /* Perform subtract with borrow. */ - 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, reg, z, QREG_CC_N, QREG_CC_X); - tcg_temp_free(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 subtraction. */ - tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg); - tcg_gen_xor_i32(QREG_CC_Z, reg, src); - tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z); + /* 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_mov_i32(QREG_CC_Z, QREG_CC_N); + tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ + gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0); + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); - tcg_gen_mov_i32(reg, QREG_CC_N); + set_cc_op(s, CC_OP_FLAGS); + + /* result is in QREG_CC_N */ +} + +DISAS_INSN(subx_reg) +{ + TCGv dest; + TCGv src; + int opsize; + + 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) { TCGv src; @@ -2058,29 +2123,76 @@ 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, src, z; + TCGv tmp; - reg = DREG(insn, 9); - src = DREG(insn, 0); + gen_flush_flags(s); /* compute old Z */ - /* Perform addition with carry. */ - z = tcg_const_i32(0); - tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, z, reg, z); - tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, z); - tcg_temp_free(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, reg); - tcg_gen_xor_i32(QREG_CC_Z, reg, src); - tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z); + + 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_mov_i32(QREG_CC_Z, QREG_CC_N); + tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */ + gen_ext(QREG_CC_Z, QREG_CC_Z, opsize, 0); + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); - tcg_gen_mov_i32(reg, QREG_CC_N); + set_cc_op(s, CC_OP_FLAGS); + + /* result is in QREG_CC_N */ +} + +DISAS_INSN(addx_reg) +{ + TCGv dest; + TCGv src; + int opsize; + + 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); } DISAS_INSN(shift_im) @@ -3128,6 +3240,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); @@ -3195,7 +3309,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); @@ -3224,7 +3341,10 @@ void register_m68k_insns (CPUM68KState *env) BASE(and, c000, f000); 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);