From patchwork Tue Oct 18 18:50:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 120487 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C0EC5B6F94 for ; Wed, 19 Oct 2011 05:53:36 +1100 (EST) Received: from localhost ([::1]:57203 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RGEmu-0003BJ-4n for incoming@patchwork.ozlabs.org; Tue, 18 Oct 2011 14:53:20 -0400 Received: from eggs.gnu.org ([140.186.70.92]:43892) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RGEln-0001q7-Hx for qemu-devel@nongnu.org; Tue, 18 Oct 2011 14:52:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RGElf-0002G4-Vw for qemu-devel@nongnu.org; Tue, 18 Oct 2011 14:52:06 -0400 Received: from mail-wy0-f173.google.com ([74.125.82.173]:53655) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RGElf-0002CC-Hh for qemu-devel@nongnu.org; Tue, 18 Oct 2011 14:52:03 -0400 Received: by mail-wy0-f173.google.com with SMTP id 15so1034654wyh.4 for ; Tue, 18 Oct 2011 11:52:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=DPVENwq+6S3csNY9gOWmwVAOiBmPDqbDnwB/8/dq6DQ=; b=vc3hszYPC1HgbIIAqSaHEgNoIEoVXm3NxJkoe2vCVA98FVpqVJuQxhe6r2OlIzCk3k dVKwCRgaez6NQ/odJXi8H4eapDTO8sXY7oMjimNt0thjMw0gxBLFCr7kgMUiGNRd6npy EHTmQL+2ishV8ynkutESDTDd6F41SYYFuo4rY= Received: by 10.227.129.138 with SMTP id o10mr1299541wbs.14.1318963922806; Tue, 18 Oct 2011 11:52:02 -0700 (PDT) Received: from localhost.localdomain (c-71-227-161-214.hsd1.wa.comcast.net. [71.227.161.214]) by mx.google.com with ESMTPS id 11sm5169602wby.15.2011.10.18.11.52.00 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 18 Oct 2011 11:52:02 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 18 Oct 2011 11:50:37 -0700 Message-Id: <1318963843-25100-16-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.6.4 In-Reply-To: <1318963843-25100-1-git-send-email-rth@twiddle.net> References: <1318963843-25100-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 74.125.82.173 Cc: blauwirbel@gmail.com Subject: [Qemu-devel] [PATCH 15/21] target-sparc: Implement EDGE* 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: Richard Henderson --- target-sparc/translate.c | 177 +++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 175 insertions(+), 2 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 1edf255..df82ecc 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2212,6 +2212,109 @@ static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env) tcg_temp_free_i32(r_tl); } + +static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2, + int width, bool cc, bool left) +{ + TCGv lo1, lo2, t1, t2; + uint64_t amask, tabl, tabr; + int shift, imask, omask; + + if (cc) { + tcg_gen_mov_tl(cpu_cc_src, s1); + tcg_gen_mov_tl(cpu_cc_src2, s2); + tcg_gen_sub_tl(cpu_cc_dst, s1, s2); + tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); + dc->cc_op = CC_OP_SUB; + } + + /* Theory of operation: there are two tables, left and right (not to + be confused with the left and right versions of the opcode). These + are indexed by the low 3 bits of the inputs. To make things "easy", + these tables are loaded into two constants, TABL and TABR below. + The operation index = (input & imask) << shift calculates the index + into the constant, while val = (table >> index) & omask calculates + the value we're looking for. */ + switch (width) { + case 8: + imask = 0x7; + shift = 3; + omask = 0xff; + if (left) { + tabl = 0x80c0e0f0f8fcfeffULL; + tabr = 0xff7f3f1f0f070301ULL; + } else { + tabl = 0x0103070f1f3f7fffULL; + tabr = 0xfffefcf8f0e0c080ULL; + } + break; + case 16: + imask = 0x6; + shift = 1; + omask = 0xf; + if (left) { + tabl = 0x8cef; + tabr = 0xf731; + } else { + tabl = 0x137f; + tabr = 0xfec8; + } + break; + case 32: + imask = 0x4; + shift = 0; + omask = 0x3; + if (left) { + tabl = (2 << 2) | 3; + tabr = (3 << 2) | 1; + } else { + tabl = (1 << 2) | 3; + tabr = (3 << 2) | 2; + } + break; + default: + abort(); + } + + lo1 = tcg_temp_new(); + lo2 = tcg_temp_new(); + tcg_gen_andi_tl(lo1, s1, imask); + tcg_gen_andi_tl(lo2, s2, imask); + tcg_gen_shli_tl(lo1, lo1, shift); + tcg_gen_shli_tl(lo2, lo2, shift); + + t1 = tcg_const_tl(tabl); + t2 = tcg_const_tl(tabr); + tcg_gen_shr_tl(lo1, t1, lo1); + tcg_gen_shr_tl(lo2, t2, lo2); + tcg_gen_andi_tl(dst, lo1, omask); + tcg_gen_andi_tl(lo2, lo2, omask); + + amask = -8; + if (AM_CHECK(dc)) { + amask &= 0xffffffffULL; + } + tcg_gen_andi_tl(s1, s1, amask); + tcg_gen_andi_tl(s2, s2, amask); + + /* We want to compute + dst = (s1 == s2 ? lo1 : lo1 & lo2). + We've already done dst = lo1, so this reduces to + dst &= (s1 == s2 ? -1 : lo2) + Which we perform by + lo2 |= -(s1 == s2) + dst &= lo2 + */ + tcg_gen_setcond_tl(TCG_COND_EQ, t1, s1, s2); + tcg_gen_neg_tl(t1, t1); + tcg_gen_or_tl(lo2, lo2, t1); + tcg_gen_and_tl(dst, dst, lo2); + + tcg_temp_free(lo1); + tcg_temp_free(lo2); + tcg_temp_free(t1); + tcg_temp_free(t2); +} #endif #define CHECK_IU_FEATURE(dc, FEATURE) \ @@ -3945,19 +4048,89 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) switch (opf) { case 0x000: /* VIS I edge8cc */ + CHECK_FPU_FEATURE(dc, VIS1); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x001: /* VIS II edge8n */ + CHECK_FPU_FEATURE(dc, VIS2); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x002: /* VIS I edge8lcc */ + CHECK_FPU_FEATURE(dc, VIS1); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x003: /* VIS II edge8ln */ + CHECK_FPU_FEATURE(dc, VIS2); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x004: /* VIS I edge16cc */ + CHECK_FPU_FEATURE(dc, VIS1); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x005: /* VIS II edge16n */ + CHECK_FPU_FEATURE(dc, VIS2); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x006: /* VIS I edge16lcc */ + CHECK_FPU_FEATURE(dc, VIS1); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x007: /* VIS II edge16ln */ + CHECK_FPU_FEATURE(dc, VIS2); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x008: /* VIS I edge32cc */ + CHECK_FPU_FEATURE(dc, VIS1); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x009: /* VIS II edge32n */ + CHECK_FPU_FEATURE(dc, VIS2); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x00a: /* VIS I edge32lcc */ + CHECK_FPU_FEATURE(dc, VIS1); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x00b: /* VIS II edge32ln */ - // XXX - goto illegal_insn; + CHECK_FPU_FEATURE(dc, VIS2); + gen_movl_reg_TN(rs1, cpu_src1); + gen_movl_reg_TN(rs2, cpu_src2); + gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1); + gen_movl_TN_reg(rd, cpu_dst); + break; case 0x010: /* VIS I array8 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = get_src1(insn, cpu_src1);