From patchwork Sun Aug 9 20:13:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 505472 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 B6F17140321 for ; Mon, 10 Aug 2015 06:26:18 +1000 (AEST) Received: from localhost ([::1]:56222 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZOXAe-0007AV-ST for incoming@patchwork.ozlabs.org; Sun, 09 Aug 2015 16:26:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52293) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZOWz7-0000iN-Bo for qemu-devel@nongnu.org; Sun, 09 Aug 2015 16:14:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZOWz5-0005TA-Gs for qemu-devel@nongnu.org; Sun, 09 Aug 2015 16:14:21 -0400 Received: from smtp4-g21.free.fr ([2a01:e0c:1:1599::13]:3077) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZOWz5-0005T2-83 for qemu-devel@nongnu.org; Sun, 09 Aug 2015 16:14:19 -0400 Received: from Quad.localdomain (unknown [78.238.229.36]) by smtp4-g21.free.fr (Postfix) with ESMTPS id 7982A4C803D; Sun, 9 Aug 2015 22:14:18 +0200 (CEST) From: Laurent Vivier To: qemu-devel@nongnu.org Date: Sun, 9 Aug 2015 22:13:44 +0200 Message-Id: <1439151229-27747-26-git-send-email-laurent@vivier.eu> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1439151229-27747-1-git-send-email-laurent@vivier.eu> References: <1439151229-27747-1-git-send-email-laurent@vivier.eu> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a01:e0c:1:1599::13 Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com, Andreas Schwab , Laurent Vivier , gerg@uclinux.org Subject: [Qemu-devel] [PATCH for-2.5 25/30] m68k: add abcd, sbcd, nbcd instructions 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: Laurent Vivier --- target-m68k/helper.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ target-m68k/helper.h | 3 ++ target-m68k/translate.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 8c10fbc..f4be52b 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -938,3 +938,94 @@ void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc) res |= (uint64_t)(val & 0xffff0000) << 16; env->macc[acc + 1] = res; } + +uint32_t HELPER(abcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest) +{ + uint16_t hi, lo; + uint16_t res; + uint32_t flags; + int extend = 0; + + flags = env->cc_dest; + flags &= ~CCF_C; + + lo = (src & 0x0f) + (dest & 0x0f); + if (env->cc_x) { + lo++; + } + hi = (src & 0xf0) + (dest & 0xf0); + + res = hi + lo; + if (lo > 9) { + res += 0x06; + } + + /* C and X flags: set if decimal carry, cleared otherwise */ + + if ((res & 0x3F0) > 0x90) { + res += 0x60; + flags |= CCF_C; + extend = 1; + } + + /* Z flag: cleared if nonzero */ + + if (res & 0xff) { + flags &= ~CCF_Z; + } + + dest = (dest & 0xffffff00) | (res & 0xff); + + env->cc_x = extend; + env->cc_dest = flags; + + return dest; +} + +uint32_t HELPER(sbcd_cc)(CPUM68KState *env, uint32_t src, uint32_t dest) +{ + uint16_t hi, lo; + uint16_t res; + uint32_t flags; + int bcd = 0, carry = 0, extend = 0; + + flags = env->cc_dest; + flags &= CCF_C; + + if (env->cc_x) { + carry = 1; + } + + lo = (dest & 0x0f) - (src & 0x0f) - carry; + hi = (dest & 0xf0) - (src & 0xf0); + + res = hi + lo; + if (lo & 0xf0) { + res -= 0x06; + bcd = 0x06; + } + + if ((((dest & 0xff) - (src & 0xff) - carry) & 0x100) > 0xff) { + res -= 0x60; + } + + /* C and X flags: set if decimal carry, cleared otherwise */ + + if ((((dest & 0xff) - (src & 0xff) - (bcd + carry)) & 0x300) > 0xff) { + flags |= CCF_C; + extend = 1; + } + + /* Z flag: cleared if nonzero */ + + if (res & 0xff) { + flags &= ~CCF_Z; + } + + dest = (dest & 0xffffff00) | (res & 0xff); + + env->cc_x = extend; + env->cc_dest = flags; + + return dest; +} diff --git a/target-m68k/helper.h b/target-m68k/helper.h index 81fb7db..9b54ebf 100644 --- a/target-m68k/helper.h +++ b/target-m68k/helper.h @@ -50,3 +50,6 @@ DEF_HELPER_3(set_mac_extu, void, env, i32, i32) DEF_HELPER_2(flush_flags, i32, env, i32) DEF_HELPER_2(raise_exception, void, env, i32) + +DEF_HELPER_3(abcd_cc, i32, env, i32, i32) +DEF_HELPER_3(sbcd_cc, i32, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index cb746d7..67527fe 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1146,6 +1146,83 @@ DISAS_INSN(divl) set_cc_op(s, CC_OP_FLAGS); } +DISAS_INSN(abcd_reg) +{ + TCGv src; + TCGv dest; + + src = DREG(insn, 0); + dest = DREG(insn, 9); + gen_flush_flags(s); + gen_helper_abcd_cc(dest, cpu_env, src, dest); +} + +DISAS_INSN(abcd_mem) +{ + TCGv src; + TCGv addr_src; + TCGv dest; + TCGv addr_dest; + + addr_src = AREG(insn, 0); + tcg_gen_subi_i32(addr_src, addr_src, OS_BYTE); + src = gen_load(s, OS_BYTE, addr_src, 0); + + addr_dest = AREG(insn, 9); + tcg_gen_subi_i32(addr_dest, addr_dest, OS_BYTE); + dest = gen_load(s, OS_BYTE, addr_dest, 0); + + gen_flush_flags(s); + gen_helper_abcd_cc(dest, cpu_env, src, dest); + + gen_store(s, OS_BYTE, addr_dest, dest); +} + +DISAS_INSN(sbcd_reg) +{ + TCGv src; + TCGv dest; + + src = DREG(insn, 0); + dest = DREG(insn, 9); + gen_flush_flags(s); + gen_helper_sbcd_cc(dest, cpu_env, src, dest); +} + +DISAS_INSN(sbcd_mem) +{ + TCGv src; + TCGv addr_src; + TCGv dest; + TCGv addr_dest; + + addr_src = AREG(insn, 0); + tcg_gen_subi_i32(addr_src, addr_src, OS_BYTE); + src = gen_load(s, OS_BYTE, addr_src, 0); + + addr_dest = AREG(insn, 9); + tcg_gen_subi_i32(addr_dest, addr_dest, OS_BYTE); + dest = gen_load(s, OS_BYTE, addr_dest, 0); + + gen_flush_flags(s); + gen_helper_sbcd_cc(dest, cpu_env, src, dest); + + gen_store(s, OS_BYTE, addr_dest, dest); +} + +DISAS_INSN(nbcd) +{ + TCGv dest; + TCGv addr; + + SRC_EA(env, dest, OS_BYTE, -1, &addr); + + gen_flush_flags(s); + gen_helper_sbcd_cc(dest, cpu_env, dest, tcg_const_i32(0)); + + DEST_EA(env, insn, OS_BYTE, dest, &addr); +} + DISAS_INSN(addsub) { TCGv reg; @@ -3239,6 +3316,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(not, 4600, ff00, M68000); INSN(undef, 46c0, ffc0, M68000); INSN(move_to_sr, 46c0, ffc0, CF_ISA_A); + INSN(nbcd, 4800, ffc0, M68000); INSN(linkl, 4808, fff8, M68000); INSN(pea, 4840, ffc0, CF_ISA_A); INSN(pea, 4840, ffc0, M68000); @@ -3315,6 +3393,8 @@ void register_m68k_insns (CPUM68KState *env) INSN(or, 8000, f000, M68000); INSN(divw, 80c0, f0c0, CF_ISA_A); INSN(divw, 80c0, f0c0, M68000); + INSN(sbcd_reg, 8100, f1f8, M68000); + INSN(sbcd_mem, 8108, f1f8, M68000); INSN(addsub, 9000, f000, CF_ISA_A); INSN(addsub, 9000, f000, M68000); INSN(subx, 9180, f1f8, CF_ISA_A); @@ -3348,6 +3428,8 @@ void register_m68k_insns (CPUM68KState *env) INSN(and, c000, f000, M68000); INSN(mulw, c0c0, f0c0, CF_ISA_A); INSN(mulw, c0c0, f0c0, M68000); + INSN(abcd_reg, c100, f1f8, M68000); + INSN(abcd_mem, c108, f1f8, M68000); INSN(addsub, d000, f000, CF_ISA_A); INSN(addsub, d000, f000, M68000); INSN(addx, d180, f1f8, CF_ISA_A);