From patchwork Mon Jan 30 18:16:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 721674 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 3vByjr23drz9tk4 for ; Tue, 31 Jan 2017 05:34:55 +1100 (AEDT) Received: from localhost ([::1]:34418 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cYGmy-0001uH-Q4 for incoming@patchwork.ozlabs.org; Mon, 30 Jan 2017 13:34:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51198) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cYGWI-0003BF-65 for qemu-devel@nongnu.org; Mon, 30 Jan 2017 13:17:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cYGWE-0002Ep-2y for qemu-devel@nongnu.org; Mon, 30 Jan 2017 13:17:38 -0500 Received: from mout.kundenserver.de ([217.72.192.74]:64092) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cYGWD-0002EW-N5 for qemu-devel@nongnu.org; Mon, 30 Jan 2017 13:17:34 -0500 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue103 [212.227.15.183]) with ESMTPSA (Nemesis) id 0MDEgG-1ciEGv00Ts-00Gbnm; Mon, 30 Jan 2017 19:16:45 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Mon, 30 Jan 2017 19:16:28 +0100 Message-Id: <20170130181634.13934-11-laurent@vivier.eu> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170130181634.13934-1-laurent@vivier.eu> References: <20170130181634.13934-1-laurent@vivier.eu> MIME-Version: 1.0 X-Provags-ID: V03:K0:iSGF4k/Jiu8yDMQCE20tS4x4B7SVVvN+Dv6aYLSS6L1eaZosUse B3QcgoIvkACRPYRVZouiroNzY6M4fzA1f2+tUM+UlL6VfzZmUoZlRUKP9VGlcvC6W2HrOaQ WnZIRXfbAjL2bT/s8Svz2JJQTNXiTRVbGrBSAJy2eL1vEeCrE2y7v5PpnFNxSVMNHX2rNF4 ql07Nm3s1Nxi5cB+i3x8A== X-UI-Out-Filterresults: notjunk:1; V01:K0:z0gMH71M5Rs=:BRqBQKjETph87MMlfbO+XS n5CwkL3hF74TVTo6Xa2PDIWkUTJjs6DwYMMCn//+YTTjnOImNoy7G8hI0y67Xe2ZEBRvVzZnk 7HtKZ350plP1qo4TpLTIXD8taKqoNeFBgftgpa/25a5Qg36vTb+WFZoXBnRvEp4mCKPyRuADN JS5ZVMOTegOlzF59LZEyRtYGrDYhsIP4fp3RPQ/DiWyXNwyDVZrd3RCN4u35AudZMRupziXyo vQyhFEVtySiu4WUEIV8E8vHzGCtEQfpQjUr8LVzhYG4De1KSMhhsZt6pe86LybiDPar5839zk UiZeKVm/L9Giz+jOAn2hsfrLx+lxnKT1LpX9NQyDu9smyLTaaEE/t/BEI+Lcl/rIAuNI0CDr0 ONu/npaRme9cwt7+ZmqhoeHmS24jfYwr/U4yvqQrVq7fXMFQS8VvBATFnLQkTDdPZNLHbkH9O xJvnZgP/3f1OWfZCSvSa7kcfzbyu31bY0WF+TXkPY8IErv2ASEDMehqd0Y+53tkOiZ6TU1swy xNBPh6LXND+IbQeYEHqvYtJ/7bSRKris2NFMQJXh5XnyCzjCa6soyu7irFf0OjL7odHd6azBJ kZ3Ef0r032AAVFJ66ztHWIwAkIZAm++k2oFSUW92FyJAEmIOpkoIqajxnv35yRIHQQpW/Ppvc gaorq1BIGpiGWxHZ/XJHmS5Vh3XYtivPBH2m3WWSvCp92Au4aw5mFS9z06B4Cc8VMCEk49H42 wR9+WBgrS0tfk5eX X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.74 Subject: [Qemu-devel] [PATCH v2 10/16] target-m68k: add fscc. 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 , Aurelien Jarno , Richard Henderson Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" use DisasCompare with FPU conditions in fscc and fbcc. Signed-off-by: Laurent Vivier --- target/m68k/translate.c | 228 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 153 insertions(+), 75 deletions(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 699c939..3fc744d 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4654,139 +4654,215 @@ undef: disas_undef_fpu(env, s, insn); } -DISAS_INSN(fbcc) +static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond) { - uint32_t offset; - uint32_t addr; - TCGLabel *l1; - TCGv tmp; - - addr = s->pc; - offset = cpu_ldsw_code(env, s->pc); - s->pc += 2; - if (insn & (1 << 6)) { - offset = (offset << 16) | read_im16(env, s); - } - - l1 = gen_new_label(); + c->g1 = 0; + c->v2 = tcg_const_i32(0); + c->g2 = 1; /* TODO: Raise BSUN exception. */ - /* Jump to l1 if condition is true. */ - switch (insn & 0x3f) { + switch (cond) { case 0: /* False */ case 16: /* Signaling False */ + c->v1 = c->v2; + c->tcond = TCG_COND_NEVER; break; case 1: /* EQual Z */ case 17: /* Signaling EQual Z */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_Z); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_Z); + c->tcond = TCG_COND_NE; break; case 2: /* Ordered Greater Than !(A || Z || N) */ case 18: /* Greater Than !(A || Z || N) */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + c->tcond = TCG_COND_EQ; break; case 3: /* Ordered Greater than or Equal Z || !(A || N) */ case 19: /* Greater than or Equal Z || !(A || N) */ assert(FPSR_CC_A == (FPSR_CC_N >> 3)); - tmp = tcg_temp_new(); - tcg_gen_shli_i32(tmp, QREG_FPSR, 3); - tcg_gen_or_i32(tmp, tmp, QREG_FPSR); - tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N); - tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_Z); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_shli_i32(c->v1, QREG_FPSR, 3); + tcg_gen_or_i32(c->v1, c->v1, QREG_FPSR); + tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); + tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_Z); + c->tcond = TCG_COND_NE; break; case 4: /* Ordered Less Than !(!N || A || Z); */ case 20: /* Less Than !(!N || A || Z); */ - tmp = tcg_temp_new(); - tcg_gen_xori_i32(tmp, QREG_FPSR, FPSR_CC_N); - tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_xori_i32(c->v1, QREG_FPSR, FPSR_CC_N); + tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z); + c->tcond = TCG_COND_EQ; break; case 5: /* Ordered Less than or Equal Z || (N && !A) */ case 21: /* Less than or Equal Z || (N && !A) */ assert(FPSR_CC_A == (FPSR_CC_N >> 3)); - tmp = tcg_temp_new(); - tcg_gen_xori_i32(tmp, QREG_FPSR, FPSR_CC_A); - tcg_gen_shli_i32(tmp, tmp, 3); - tcg_gen_ori_i32(tmp, tmp, FPSR_CC_Z); - tcg_gen_and_i32(tmp, tmp, QREG_FPSR); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_xori_i32(c->v1, QREG_FPSR, FPSR_CC_A); + tcg_gen_shli_i32(c->v1, c->v1, 3); + tcg_gen_ori_i32(c->v1, c->v1, FPSR_CC_Z); + tcg_gen_and_i32(c->v1, c->v1, QREG_FPSR); + c->tcond = TCG_COND_NE; break; case 6: /* Ordered Greater or Less than !(A || Z) */ case 22: /* Greater or Less than !(A || Z) */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z); + c->tcond = TCG_COND_EQ; break; case 7: /* Ordered !A */ case 23: /* Greater, Less or Equal !A */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_A); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A); + c->tcond = TCG_COND_EQ; break; case 8: /* Unordered A */ case 24: /* Not Greater, Less or Equal A */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_A); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A); + c->tcond = TCG_COND_NE; break; case 9: /* Unordered or Equal A || Z */ case 25: /* Not Greater or Less then A || Z */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z); + c->tcond = TCG_COND_NE; break; case 10: /* Unordered or Greater Than A || !(N || Z)) */ case 26: /* Not Less or Equal A || !(N || Z)) */ assert(FPSR_CC_Z == (FPSR_CC_N >> 1)); - tmp = tcg_temp_new(); - tcg_gen_shli_i32(tmp, QREG_FPSR, 1); - tcg_gen_or_i32(tmp, tmp, QREG_FPSR); - tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N); - tcg_gen_andi_i32(tmp, tmp, FPSR_CC_N | FPSR_CC_A); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_shli_i32(c->v1, QREG_FPSR, 1); + tcg_gen_or_i32(c->v1, c->v1, QREG_FPSR); + tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); + tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A); + c->tcond = TCG_COND_NE; break; case 11: /* Unordered or Greater or Equal A || Z || !N */ case 27: /* Not Less Than A || Z || !N */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); - tcg_gen_xori_i32(tmp, tmp, FPSR_CC_N); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); + tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); + c->tcond = TCG_COND_NE; break; case 12: /* Unordered or Less Than A || (N && !Z) */ case 28: /* Not Greater than or Equal A || (N && !Z) */ assert(FPSR_CC_Z == (FPSR_CC_N >> 1)); - tmp = tcg_temp_new(); - tcg_gen_xori_i32(tmp, QREG_FPSR, FPSR_CC_Z); - tcg_gen_shli_i32(tmp, tmp, 1); - tcg_gen_ori_i32(tmp, tmp, FPSR_CC_A); - tcg_gen_and_i32(tmp, tmp, QREG_FPSR); - tcg_gen_andi_i32(tmp, tmp, FPSR_CC_A | FPSR_CC_N); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_xori_i32(c->v1, QREG_FPSR, FPSR_CC_Z); + tcg_gen_shli_i32(c->v1, c->v1, 1); + tcg_gen_ori_i32(c->v1, c->v1, FPSR_CC_A); + tcg_gen_and_i32(c->v1, c->v1, QREG_FPSR); + tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N); + c->tcond = TCG_COND_NE; break; case 13: /* Unordered or Less or Equal A || Z || N */ case 29: /* Not Greater Than A || Z || N */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); - tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); + c->tcond = TCG_COND_NE; break; case 14: /* Not Equal !Z */ case 30: /* Signaling Not Equal !Z */ - tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_FPSR, FPSR_CC_Z); - tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1); + c->v1 = tcg_temp_new(); + c->g1 = 1; + tcg_gen_andi_i32(c->v1, QREG_FPSR, FPSR_CC_Z); + c->tcond = TCG_COND_EQ; break; case 15: /* True */ case 31: /* Signaling True */ - tcg_gen_br(l1); + c->v1 = c->v2; + c->tcond = TCG_COND_ALWAYS; break; } +} + +static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1) +{ + DisasCompare c; + + gen_fcc_cond(&c, s, cond); + tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1); + free_cond(&c); +} + +DISAS_INSN(fbcc) +{ + uint32_t offset; + uint32_t base; + TCGLabel *l1; + + base = s->pc; + offset = (int16_t)read_im16(env, s); + if (insn & (1 << 6)) { + offset = (offset << 16) | read_im16(env, s); + } + + l1 = gen_new_label(); + update_cc_op(s); + gen_fjmpcc(s, insn & 0x3f, l1); gen_jmp_tb(s, 0, s->pc); gen_set_label(l1); - gen_jmp_tb(s, 1, addr + offset); + gen_jmp_tb(s, 1, base + offset); +} + +DISAS_INSN(fscc_mem) +{ + TCGLabel *l1, *l2; + TCGv taddr; + TCGv addr; + uint16_t ext; + + ext = read_im16(env, s); + + taddr = gen_lea(env, s, insn, OS_BYTE); + if (IS_NULL_QREG(taddr)) { + gen_addr_fault(s); + return; + } + addr = tcg_temp_local_new(); + tcg_gen_mov_i32(addr, taddr); + l1 = gen_new_label(); + l2 = gen_new_label(); + gen_fjmpcc(s, ext & 0x3f, l1); + gen_store(s, OS_BYTE, addr, tcg_const_i32(0x00)); + tcg_gen_br(l2); + gen_set_label(l1); + gen_store(s, OS_BYTE, addr, tcg_const_i32(0xff)); + gen_set_label(l2); + tcg_temp_free(addr); +} + +DISAS_INSN(fscc_reg) +{ + TCGLabel *l1; + TCGv reg; + uint16_t ext; + + ext = read_im16(env, s); + + reg = DREG(insn, 0); + + l1 = gen_new_label(); + tcg_gen_ori_i32(reg, reg, 0x000000ff); + gen_fjmpcc(s, ext & 0x3f, l1); + tcg_gen_andi_i32(reg, reg, 0xffffff00); + gen_set_label(l1); } DISAS_INSN(frestore) @@ -5366,6 +5442,8 @@ void register_m68k_insns (CPUM68KState *env) INSN(frestore, f340, ffc0, CF_FPU); INSN(fsave, f340, ffc0, CF_FPU); INSN(fpu, f200, ffc0, FPU); + INSN(fscc_mem, f240, ffc0, FPU); + INSN(fscc_reg, f240, fff8, FPU); INSN(fbcc, f280, ff80, FPU); INSN(frestore, f340, ffc0, FPU); INSN(fsave, f340, ffc0, FPU);