From patchwork Wed May 4 21:21:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 9018931 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E27A69F39D for ; Wed, 4 May 2016 21:26:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EA6BC203E6 for ; Wed, 4 May 2016 21:26:51 +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 C524D203DF for ; Wed, 4 May 2016 21:26:50 +0000 (UTC) Received: from localhost ([::1]:50386 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ay4Ji-0000lH-Sv for patchwork-qemu-devel@patchwork.kernel.org; Wed, 04 May 2016 17:26:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51325) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ay4F9-0000YB-S8 for qemu-devel@nongnu.org; Wed, 04 May 2016 17:22:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ay4Ex-0006VV-Ou for qemu-devel@nongnu.org; Wed, 04 May 2016 17:21:58 -0400 Received: from mout.kundenserver.de ([217.72.192.75]:56302) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ay4Ex-0006Nb-Er for qemu-devel@nongnu.org; Wed, 04 May 2016 17:21:51 -0400 Received: from Quad.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue104) with ESMTPSA (Nemesis) id 0MSrBt-1b88JG0rAb-00RtPf; Wed, 04 May 2016 23:21:35 +0200 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Wed, 4 May 2016 23:21:03 +0200 Message-Id: <1462396869-22424-7-git-send-email-laurent@vivier.eu> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1462396869-22424-1-git-send-email-laurent@vivier.eu> References: <1462392752-17703-1-git-send-email-laurent@vivier.eu> <1462396869-22424-1-git-send-email-laurent@vivier.eu> X-Provags-ID: V03:K0:JTLDA/DsstePpKew6t+2ild5sG77P7g0pKqgcHGV6GkfzmyWtyy jOwmzt4za/1PE01ojkXGsatq2USU8gf7IhctGMMxVeYYT34eEmI8vMXlgUH7oxnsBmcmCCP Pp6uXINmbjHYsvvc4bqGmpdHRLj8kHdkTnUuRJuh5jmb60SNJZ+s7QJYDie4gh44SC/vlsF Wuf+GMpU4q6WrwWwPNCXg== X-UI-Out-Filterresults: notjunk:1; V01:K0:DQ/k5f/b44k=:FdYlkCXo1m102JToZ/QUf1 //OxQAGb3Kw196TOgzsUP5bQ5BomUx0dw9CFrbLwjDwsn9wfWi+tMqNsFAtnnCA9qTYawNuZT 7UtHnKONAEXYrdt9dSXDgvhsaiH0ETFdrijqHMar+21/U5H3p3jRfagnnY1IS43fiY1YuRlCf zSLJfh6FOWPeT8xNn4SSJ+uKy+lDqybSjru25NRhYfyGQlD0/TX5hki2B/qTFKkFxiAPJbQ9x po3jYzGc9h8K1o43QDFwlMAKNo3cx6CdZd5K+ODftUWWm+y8i+DEX6ckpeqx4wGkfCK8CFg4Y vT5xJICQc6EN3GL+q3BY2CH5zIkULA957+9c0PnLySLZcD9d0qeeOMNFE/AsXK0b6qtngJKJJ dFIgdUSByiZtJBZ4Ujxn0elvpV7NDyM9+KVImQKGK5WT4jsfeNfIO7WXfOXFv3JSbtlwzH4xW M+g9KY5dlfITc8imBieuRG44ODWSb3EtuthOwUJJ4zfHGEkzFgBOvtUaJiMY8qxQwXgwLJmYT mmK3wjHe18QqU5lOSbPULzLjYEkoPNdpTTSCmBxQyoDvSvmWBzVpBXhD4CWxoOx/dglzLUvuw P6pEbjX0SDkuso+sbTOnNpynC0FdMsnjlf73NPo0tvFl0G8Vv8MpuSPaAkFOs5CCJmR8C6GrM 23TIdogkvv52T47TWD61VG9Q06fYRHU4GTn3X7+7jklzVHEXLL8htTo6Io6IKd/LrbT8= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 217.72.192.75 Subject: [Qemu-devel] [PATCH 46/52] target-m68k: introduce byte and word cc_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, rth@twiddle.net 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/cpu.h | 6 +-- target-m68k/helper.c | 25 +++++++++---- target-m68k/translate.c | 99 ++++++++++++++++++++++++++++++------------------- 3 files changed, 80 insertions(+), 50 deletions(-) diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index 5ce77e4..1112502 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -147,11 +147,11 @@ typedef enum { CC_OP_FLAGS, /* X in cc_x, C = X, N in cc_n, Z in cc_n, V via cc_n/cc_v. */ - CC_OP_ADD, - CC_OP_SUB, + CC_OP_ADDB, CC_OP_ADDW, CC_OP_ADDL, + CC_OP_SUBB, CC_OP_SUBW, CC_OP_SUBL, /* X in cc_x, {N,Z,C,V} via cc_n/cc_v. */ - CC_OP_CMP, + CC_OP_CMPB, CC_OP_CMPW, CC_OP_CMPL, /* X in cc_x, C = 0, V = 0, N in cc_n, Z in cc_n. */ CC_OP_LOGIC, diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 76dda44..4d346a7 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -544,32 +544,41 @@ void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc) } } +#define EXTSIGN(val, index) ( \ + (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \ +) #define COMPUTE_CCR(op, x, n, z, v, c) { \ switch (op) { \ case CC_OP_FLAGS: \ /* Everything in place. */ \ break; \ - case CC_OP_ADD: \ + case CC_OP_ADDB: \ + case CC_OP_ADDW: \ + case CC_OP_ADDL: \ res = n; \ src2 = v; \ - src1 = res - src2; \ + src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \ c = x; \ z = n; \ v = (res ^ src1) & ~(src1 ^ src2); \ break; \ - case CC_OP_SUB: \ + case CC_OP_SUBB: \ + case CC_OP_SUBW: \ + case CC_OP_SUBL: \ res = n; \ src2 = v; \ - src1 = res + src2; \ + src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \ c = x; \ z = n; \ v = (res ^ src1) & (src1 ^ src2); \ break; \ - case CC_OP_CMP: \ + case CC_OP_CMPB: \ + case CC_OP_CMPW: \ + case CC_OP_CMPL: \ src1 = n; \ src2 = v; \ - res = src1 - src2; \ + res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \ n = res; \ z = res; \ c = src1 < src2; \ @@ -590,16 +599,16 @@ uint32_t cpu_m68k_get_ccr(CPUM68KState *env) uint32_t res, src1, src2; x = env->cc_x; - c = env->cc_c; n = env->cc_n; z = env->cc_z; v = env->cc_v; + c = env->cc_c; COMPUTE_CCR(env->cc_op, x, n, z, v, c); n = n >> 31; - v = v >> 31; z = (z == 0); + v = v >> 31; return x*CCF_X + n*CCF_N + z*CCF_Z + v*CCF_V + c*CCF_C; } diff --git a/target-m68k/translate.c b/target-m68k/translate.c index a8e9b64..2b6ba15 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -176,9 +176,9 @@ typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn); static const uint8_t cc_op_live[CC_OP_NB] = { [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X, - [CC_OP_ADD] = CCF_X | CCF_N | CCF_V, - [CC_OP_SUB] = CCF_X | CCF_N | CCF_V, - [CC_OP_CMP] = CCF_X | CCF_N | CCF_V, + [CC_OP_ADDB ... CC_OP_ADDL] = CCF_X | CCF_N | CCF_V, + [CC_OP_SUBB ... CC_OP_SUBL] = CCF_X | CCF_N | CCF_V, + [CC_OP_CMPB ... CC_OP_CMPL] = CCF_X | CCF_N | CCF_V, [CC_OP_LOGIC] = CCF_X | CCF_N }; @@ -452,6 +452,33 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) return add; } +/* Sign or zero extend a value. */ + +static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign) +{ + switch (opsize) { + case OS_BYTE: + if (sign) { + tcg_gen_ext8s_i32(res, val); + } else { + tcg_gen_ext8u_i32(res, val); + } + break; + case OS_WORD: + if (sign) { + tcg_gen_ext16s_i32(res, val); + } else { + tcg_gen_ext16u_i32(res, val); + } + break; + case OS_LONG: + tcg_gen_mov_i32(res, val); + break; + default: + g_assert_not_reached(); + } +} + /* Evaluate all the CC flags. */ static void gen_flush_flags(DisasContext *s) @@ -462,13 +489,16 @@ static void gen_flush_flags(DisasContext *s) case CC_OP_FLAGS: return; - case CC_OP_ADD: + case CC_OP_ADDB: + case CC_OP_ADDW: + case CC_OP_ADDL: tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); /* Compute signed overflow for addition. */ t0 = tcg_temp_new(); t1 = tcg_temp_new(); tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V); + gen_ext(t0, t0, s->cc_op - CC_OP_ADDB, 1); tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V); tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0); tcg_temp_free(t0); @@ -476,13 +506,16 @@ static void gen_flush_flags(DisasContext *s) tcg_temp_free(t1); break; - case CC_OP_SUB: + case CC_OP_SUBB: + case CC_OP_SUBW: + case CC_OP_SUBL: tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); /* Compute signed overflow for subtraction. */ t0 = tcg_temp_new(); t1 = tcg_temp_new(); tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V); + gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1); tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V); tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0); tcg_temp_free(t0); @@ -490,9 +523,12 @@ static void gen_flush_flags(DisasContext *s) tcg_temp_free(t1); break; - case CC_OP_CMP: + case CC_OP_CMPB: + case CC_OP_CMPW: + case CC_OP_CMPL: tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V); tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V); + gen_ext(QREG_CC_Z, QREG_CC_Z, s->cc_op - CC_OP_CMPB, 1); /* Compute signed overflow for subtraction. */ t0 = tcg_temp_new(); tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N); @@ -524,33 +560,6 @@ static void gen_flush_flags(DisasContext *s) s->cc_op_synced = 1; } -/* Sign or zero extend a value. */ - -static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign) -{ - switch (opsize) { - case OS_BYTE: - if (sign) { - tcg_gen_ext8s_i32(res, val); - } else { - tcg_gen_ext8u_i32(res, val); - } - break; - case OS_WORD: - if (sign) { - tcg_gen_ext16s_i32(res, val); - } else { - tcg_gen_ext16u_i32(res, val); - } - break; - case OS_LONG: - tcg_gen_mov_i32(res, val); - break; - default: - g_assert_not_reached(); - } -} - static inline TCGv gen_extend(TCGv val, int opsize, int sign) { TCGv tmp; @@ -571,10 +580,17 @@ static void gen_logic_cc(DisasContext *s, TCGv val, int opsize) set_cc_op(s, CC_OP_LOGIC); } -static void gen_update_cc_add(TCGv dest, TCGv src) +static void gen_update_cc_cmp(DisasContext *s, TCGv dest, TCGv src, int opsize) { tcg_gen_mov_i32(QREG_CC_N, dest); tcg_gen_mov_i32(QREG_CC_V, src); + set_cc_op(s, CC_OP_CMPB + opsize); +} + +static void gen_update_cc_add(TCGv dest, TCGv src, int opsize) +{ + gen_ext(QREG_CC_N, dest, opsize, 1); + tcg_gen_mov_i32(QREG_CC_V, src); } static inline int opsize_bytes(int opsize) @@ -819,7 +835,7 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) CCOp op = s->cc_op; /* The CC_OP_CMP form can handle most normal comparisons directly. */ - if (op == CC_OP_CMP) { + if (op == CC_OP_CMPB || op == CC_OP_CMPW || op == CC_OP_CMPL) { c->g1 = c->g2 = 1; c->v1 = QREG_CC_N; c->v2 = QREG_CC_V; @@ -842,6 +858,7 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) c->v2 = tcg_const_i32(0); c->v1 = tmp = tcg_temp_new(); tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V); + gen_ext(tmp, tmp, op - CC_OP_CMPB, 1); /* fallthru */ case 12: /* GE */ case 13: /* LT */ @@ -864,7 +881,6 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) c->v1 = c->v2; tcond = TCG_COND_NEVER; goto done; - case 14: /* GT (!(Z || (N ^ V))) */ case 15: /* LE (Z || (N ^ V)) */ /* Logic operations clear V, which simplifies LE to (Z || N), and since Z and N are co-located, this becomes a normal @@ -885,7 +901,9 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) case 10: /* PL (!N) */ case 11: /* MI (N) */ /* Several cases represent N normally. */ - if (op == CC_OP_ADD || op == CC_OP_SUB || op == CC_OP_LOGIC) { + if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL || + op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL || + op == CC_OP_LOGIC) { c->v1 = QREG_CC_N; tcond = TCG_COND_LT; goto done; @@ -894,7 +912,9 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) case 6: /* NE (!Z) */ case 7: /* EQ (Z) */ /* Some cases fold Z into N. */ - if (op == CC_OP_ADD || op == CC_OP_SUB || op == CC_OP_LOGIC) { + if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL || + op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL || + op == CC_OP_LOGIC) { tcond = TCG_COND_EQ; c->v1 = QREG_CC_N; goto done; @@ -903,7 +923,8 @@ static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond) case 4: /* CC (!C) */ case 5: /* CS (C) */ /* Some cases fold C into X. */ - if (op == CC_OP_ADD || op == CC_OP_SUB) { + if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL || + op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL) { tcond = TCG_COND_NE; c->v1 = QREG_CC_X; goto done;