From patchwork Mon Oct 31 10:20:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 689245 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3t6r9R15DBz9t2j for ; Mon, 31 Oct 2016 21:25:47 +1100 (AEDT) Received: from localhost ([::1]:34437 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c19ma-0007vd-ST for incoming@patchwork.ozlabs.org; Mon, 31 Oct 2016 06:25:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35769) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c19ia-0004mc-NE for qemu-devel@nongnu.org; Mon, 31 Oct 2016 06:21:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1c19iX-0004mF-FN for qemu-devel@nongnu.org; Mon, 31 Oct 2016 06:21:28 -0400 Received: from mout.kundenserver.de ([217.72.192.73]:54821) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1c19iX-0004lV-3v for qemu-devel@nongnu.org; Mon, 31 Oct 2016 06:21:25 -0400 Received: from Quad.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue102) with ESMTPSA (Nemesis) id 0LgYYX-1cdXL51oOb-00nvbA; Mon, 31 Oct 2016 11:21:06 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Mon, 31 Oct 2016 11:20:59 +0100 Message-Id: <1477909259-12284-4-git-send-email-laurent@vivier.eu> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1477909259-12284-1-git-send-email-laurent@vivier.eu> References: <1477909259-12284-1-git-send-email-laurent@vivier.eu> X-Provags-ID: V03:K0:rwwenkfa4N06IvMG8TbCshhyW5EgWP08dD7/DvB2i0w3zq4yZSQ tk4KEEtZWV/5O23NyqjYlvSN9TB2FI8A9wM61RyVU9MJKymWKFsxLjsIRyDEXoFENlf8O1V LeN85aQBvZDLbbvA0RQTSl/EeA5yT7WTkLrYX8nv/Olt5GQEXb3Q2PfdrmeCXN7TtCeiox7 jfsCcXj0lpSBtzZ88gzUA== X-UI-Out-Filterresults: notjunk:1; V01:K0:lCVgnqGNg/U=:LcqZ7Eqb+yGdl/cIbwCdGi oEltw0luT7NtLm4etgmOuihUSb1VLjevRYsf51rO0KFe1+uQr8UVdvzWuUkoffGCJGqr/3oyO fmln+t/nCeisGH0ho6r3BY5ARC62Bz9cpcKZWal0UsqQsvhBkgMLCtjJHyUE1a48ARHBIPgbJ UnSwbFhUnISijHwrQEltZk+NVkInUYOC0nt98oNZrcDpxfsYj4n9S3ieestfC+D+r7CpDwU45 MUqdkXPDSUtYRSsqhGmGEMIh/WIWdVLwY9EkOuPVPl6BCxKkpbx2vcaIe6EsboeBvzGFIAnEU OY0nzZNQSPUUQ+iqEEWZ+FH74ROOFK+ZjmfxNR40wcI0GamplmPWDmAuTbynTJlPv9lF5oM7Y A1yeutwOZ0Qjnlu27aOQcdt41y8VilPbD9WPOlvA1bT6I9hIwEgstd9IHXedU7wdQgvjZghvN x1t/MBNMvXHbSTOYfm5QXIHcnLgVesp/+6gH7YECTW4R47f1Zb6NB5q0bQBrQOiDIz+ZpeNBh ZTprEFFuxkVRQQ3ra7cxBGpNdxbA8koU/NVrhq3edcevvfByqtxs9SiLPecTSLhrlYONGvTxl Exn/iaE7N47E76nLlWxJvFWFSahBf1ZFObSzi4rMwYR14SUX1dvLr53E+Xhnrz6Y/KY+sIcsV bDZwP9uM5DlolonzK5zeQSW9duxTiD7rIkzDU1UEBVPguHKOiYM+MaBcVb4/e5B9tqIA= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 217.72.192.73 Subject: [Qemu-devel] [PATCH 3/3] target-m68k: add cas/cas2 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 , gerg@uclinux.org, schwab@linux-m68k.org, agraf@suse.de, Richard Henderson Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Implement CAS using cmpxchg. Implement CAS2, but the sequence is not atomic. Signed-off-by: Laurent Vivier --- target-m68k/translate.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 159a17d..4e66284 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1905,6 +1905,172 @@ DISAS_INSN(arith_im) tcg_temp_free(dest); } +DISAS_INSN(cas) +{ + int opsize; + TCGv addr; + uint16_t ext; + TCGv load; + TCGv cmp; + TCGMemOp opc; + + switch ((insn >> 9) & 3) { + case 1: + opsize = OS_BYTE; + opc = MO_UB; + break; + case 2: + opsize = OS_WORD; + opc = MO_TEUW; + break; + case 3: + opsize = OS_LONG; + opc = MO_TEUL; + break; + default: + g_assert_not_reached(); + } + opc |= MO_ALIGN; + + ext = read_im16(env, s); + + /* cas Dc,Du, */ + + addr = gen_lea(env, s, insn, opsize); + if (IS_NULL_QREG(addr)) { + gen_addr_fault(s); + return; + } + + cmp = gen_extend(DREG(ext, 0), opsize, 0); + + /* if == Dc then + * = Du + * Dc = (because == Dc) + * else + * Dc = + */ + + load = tcg_temp_new(); + tcg_gen_atomic_cmpxchg_i32(load, addr, cmp, DREG(ext, 6), + IS_USER(s), opc); + gen_partset_reg(opsize, DREG(ext, 0), load); + + gen_update_cc_cmp(s, load, cmp, opsize); + tcg_temp_free(load); +} + +DISAS_INSN(cas2) +{ + int opsize; + uint16_t ext1, ext2; + TCGv addr1, addr2; + TCGv load1, load2; + TCGv cmp1, cmp2; + TCGv dest, src; + TCGv store; + + switch ((insn >> 9) & 3) { + case 1: + opsize = OS_BYTE; + break; + case 2: + opsize = OS_WORD; + break; + case 3: + opsize = OS_LONG; + break; + default: + abort(); + } + + /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */ + + ext1 = read_im16(env, s); + + if (ext1 & 0x8000) { + /* Address Register */ + addr1 = AREG(ext1, 12); + } else { + /* Data Register */ + addr1 = DREG(ext1, 12); + } + + ext2 = read_im16(env, s); + if (ext2 & 0x8000) { + /* Address Register */ + addr2 = AREG(ext2, 12); + } else { + /* Data Register */ + addr2 = DREG(ext2, 12); + } + + /* FIXME: this sequence is not atomic */ + + /* if (R1) == Dc1 && (R2) == Dc2 then + * (R1) = Du1 + * (R2) = Du2 + * Dc1 = (R1) (because Dc1 == (R1)) + * Dc2 = (R2) (because Dc2 == (R2)) + * else + * Dc1 = (R1) + * Dc2 = (R2) + */ + + load1 = gen_load(s, opsize, addr1, 0); + load2 = gen_load(s, opsize, addr2, 0); + + cmp1 = gen_extend(DREG(ext1, 0), opsize, 0); + cmp2 = gen_extend(DREG(ext2, 0), opsize, 0); + + /* (R1) - Dc1 -> cc + * if Z + * (R2) - Dc2 -> cc + * + * with CC_OP_CMP, set dest and src accordingly + * dest - src -> cc + */ + + dest = tcg_temp_new(); + tcg_gen_movcond_i32(TCG_COND_EQ, dest, + load1, cmp1, + load2, load1); + src = tcg_temp_new(); + tcg_gen_movcond_i32(TCG_COND_EQ, src, + load1, cmp1, + cmp2, cmp1); + + /* if src == dest then + * (R1) = Du1 + * (R2) = Du2 + */ + + store = tcg_temp_new(); + tcg_gen_movcond_i32(TCG_COND_EQ, store, + dest, src, + DREG(ext1, 6), load1); + gen_store(s, opsize, addr1, store); + + tcg_gen_movcond_i32(TCG_COND_EQ, store, + dest, src, + DREG(ext2, 6), load2); + gen_store(s, opsize, addr2, store); + tcg_temp_free(store); + + /* Dc1 = (R1) + * Dc2 = (R2) + */ + + gen_partset_reg(opsize, DREG(ext1, 0), load1); + gen_partset_reg(opsize, DREG(ext2, 0), load2); + + tcg_gen_mov_i32(QREG_CC_N, dest); + tcg_temp_free(dest); + tcg_gen_mov_i32(QREG_CC_V, src); + tcg_temp_free(src); + set_cc_op(s, CC_OP_CMPB + opsize); +} + DISAS_INSN(byterev) { TCGv reg; @@ -3920,6 +4086,8 @@ void register_m68k_insns (CPUM68KState *env) INSN(arith_im, 0680, fff8, CF_ISA_A); INSN(arith_im, 0c00, ff38, CF_ISA_A); INSN(arith_im, 0c00, ff00, M68000); + INSN(cas, 08c0, f9c0, CAS); + INSN(cas2, 08fc, f9ff, CAS); BASE(bitop_im, 0800, ffc0); BASE(bitop_im, 0840, ffc0); BASE(bitop_im, 0880, ffc0);