From patchwork Thu Feb 20 11:17:10 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 25028 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ie0-f200.google.com (mail-ie0-f200.google.com [209.85.223.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B4FB1203C6 for ; Thu, 20 Feb 2014 11:32:00 +0000 (UTC) Received: by mail-ie0-f200.google.com with SMTP id to1sf6744469ieb.3 for ; Thu, 20 Feb 2014 03:31:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:mime-version:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list:content-type :content-transfer-encoding; bh=npPjHFC/KnSKwiAXpPjtHVFUixLrN2pZqbOjSE86LeQ=; b=bmDIm2Gtv9/CQeE6BiUY8Hkv4j5uWi28r72Vs65NWpLK9nkXmv+5z5LCiZBFxCWaxj eVpdbcUJ8/VMhqn3x6b1cuxCIl0edpjbnJ2r11LayCreFp+UFYvYuPEUq2EoWVqToek7 dvfRNr5ROg782OS4yJgJloZktao2LAAMxdjXKzAFxySsp0ulkNZ0U21uH9+wjKX7q54E Q5I2hPdg0w22QXP3Pq6mhARWp1DfxLK/CHr5+In8XZmMWgV7z0LkeTV+9xa8FrtIw4W9 NOiEm9PLKbUw/xJtbeQzEHEqpr8YwfEC1QAN0wW4gKyzO5hqVQkrZIC17XchLzv3zsZH zkLA== X-Gm-Message-State: ALoCoQm2pUEU7b6nXfaU+eZAbKHnS0uovAf+MQA7Ldjb7qx/RMwvO/bE9Ho5q9FxiaSPBEJGvzuO X-Received: by 10.43.158.9 with SMTP id ls9mr488255icc.18.1392895919700; Thu, 20 Feb 2014 03:31:59 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.106.165 with SMTP id e34ls588607qgf.29.gmail; Thu, 20 Feb 2014 03:31:59 -0800 (PST) X-Received: by 10.52.171.39 with SMTP id ar7mr587791vdc.5.1392895919483; Thu, 20 Feb 2014 03:31:59 -0800 (PST) Received: from mail-ve0-f172.google.com (mail-ve0-f172.google.com [209.85.128.172]) by mx.google.com with ESMTPS id xn9si1346199vcb.41.2014.02.20.03.31.59 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 20 Feb 2014 03:31:59 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.172 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.172; Received: by mail-ve0-f172.google.com with SMTP id c14so1705111vea.31 for ; Thu, 20 Feb 2014 03:31:59 -0800 (PST) X-Received: by 10.220.192.71 with SMTP id dp7mr671427vcb.45.1392895919138; Thu, 20 Feb 2014 03:31:59 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp51010vcz; Thu, 20 Feb 2014 03:31:58 -0800 (PST) X-Received: by 10.224.103.129 with SMTP id k1mr749157qao.97.1392895918688; Thu, 20 Feb 2014 03:31:58 -0800 (PST) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id v4si731485qcm.87.2014.02.20.03.31.58 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 20 Feb 2014 03:31:58 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:37668 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGRrC-0006iq-5x for patch@linaro.org; Thu, 20 Feb 2014 06:31:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59040) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGRen-0004EA-Eq for qemu-devel@nongnu.org; Thu, 20 Feb 2014 06:19:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WGRej-0004zR-0I for qemu-devel@nongnu.org; Thu, 20 Feb 2014 06:19:09 -0500 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:46035) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGRei-0004wV-L5 for qemu-devel@nongnu.org; Thu, 20 Feb 2014 06:19:04 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1WGRdG-0003SH-QL; Thu, 20 Feb 2014 11:17:34 +0000 From: Peter Maydell To: Anthony Liguori Date: Thu, 20 Feb 2014 11:17:10 +0000 Message-Id: <1392895054-13232-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1392895054-13232-1-git-send-email-peter.maydell@linaro.org> References: <1392895054-13232-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Cc: Blue Swirl , qemu-devel@nongnu.org, Aurelien Jarno Subject: [Qemu-devel] [PULL 06/30] target-arm: A64: Implement SIMD FP compare and set insns 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+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.172 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Alex Bennée This adds all forms of the SIMD floating point and set instructions: FCM(GT|GE|EQ|LE|LT) Most of the heavy lifting is done by either the existing neon helpers or some new helpers for the 64bit double cases. Most of the code paths are common although the 2misc versions are a little special as they compare against zero. Signed-off-by: Alex Bennée [PMM: fixed some minor bugs, added the 2-misc-scalar encoding] Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- target-arm/helper-a64.c | 19 +++++ target-arm/helper-a64.h | 3 + target-arm/translate-a64.c | 197 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 207 insertions(+), 12 deletions(-) diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c index fe90a5c..b4cab51 100644 --- a/target-arm/helper-a64.c +++ b/target-arm/helper-a64.c @@ -179,3 +179,22 @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices, } return result; } + +/* 64bit/double versions of the neon float compare functions */ +uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + return -float64_eq_quiet(a, b, fpst); +} + +uint64_t HELPER(neon_cge_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + return -float64_le(b, a, fpst); +} + +uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp) +{ + float_status *fpst = fpstp; + return -float64_lt(b, a, fpst); +} diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h index 84310e8..bf20466 100644 --- a/target-arm/helper-a64.h +++ b/target-arm/helper-a64.h @@ -29,3 +29,6 @@ DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr) DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32) DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr) DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr) +DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr) +DEF_HELPER_FLAGS_3(neon_cge_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr) +DEF_HELPER_FLAGS_3(neon_cgt_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 13f7f77..bcf32a1 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -77,6 +77,8 @@ typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32); typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32); typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64); typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64); +typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); +typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr); /* initialize TCG globals. */ void a64_translate_init(void) @@ -6049,6 +6051,9 @@ static void handle_3same_float(DisasContext *s, int size, int elements, case 0x1a: /* FADD */ gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x1c: /* FCMEQ */ + gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x1e: /* FMAX */ gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -6064,6 +6069,9 @@ static void handle_3same_float(DisasContext *s, int size, int elements, case 0x5b: /* FMUL */ gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x5c: /* FCMGE */ + gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x5f: /* FDIV */ gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -6071,6 +6079,9 @@ static void handle_3same_float(DisasContext *s, int size, int elements, gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst); gen_helper_vfp_absd(tcg_res, tcg_res); break; + case 0x7c: /* FCMGT */ + gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst); + break; default: g_assert_not_reached(); } @@ -6093,6 +6104,9 @@ static void handle_3same_float(DisasContext *s, int size, int elements, case 0x1a: /* FADD */ gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x1c: /* FCMEQ */ + gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x1e: /* FMAX */ gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -6111,6 +6125,9 @@ static void handle_3same_float(DisasContext *s, int size, int elements, case 0x5b: /* FMUL */ gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst); break; + case 0x5c: /* FCMGE */ + gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; case 0x5f: /* FDIV */ gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst); break; @@ -6118,6 +6135,9 @@ static void handle_3same_float(DisasContext *s, int size, int elements, gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst); gen_helper_vfp_abss(tcg_res, tcg_res); break; + case 0x7c: /* FCMGT */ + gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst); + break; default: g_assert_not_reached(); } @@ -6168,15 +6188,15 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn) int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6); switch (fpopcode) { case 0x1b: /* FMULX */ - case 0x1c: /* FCMEQ */ case 0x1f: /* FRECPS */ case 0x3f: /* FRSQRTS */ - case 0x5c: /* FCMGE */ case 0x5d: /* FACGE */ - case 0x7c: /* FCMGT */ case 0x7d: /* FACGT */ unsupported_encoding(s, insn); return; + case 0x1c: /* FCMEQ */ + case 0x5c: /* FCMGE */ + case 0x7c: /* FCMGT */ case 0x7a: /* FABD */ break; default: @@ -6361,6 +6381,115 @@ static void handle_2misc_64(DisasContext *s, int opcode, bool u, } } +static void handle_2misc_fcmp_zero(DisasContext *s, int opcode, + bool is_scalar, bool is_u, bool is_q, + int size, int rn, int rd) +{ + bool is_double = (size == 3); + TCGv_ptr fpst = get_fpstatus_ptr(); + + if (is_double) { + TCGv_i64 tcg_op = tcg_temp_new_i64(); + TCGv_i64 tcg_zero = tcg_const_i64(0); + TCGv_i64 tcg_res = tcg_temp_new_i64(); + NeonGenTwoDoubleOPFn *genfn; + bool swap = false; + int pass; + + switch (opcode) { + case 0x2e: /* FCMLT (zero) */ + swap = true; + /* fallthrough */ + case 0x2c: /* FCMGT (zero) */ + genfn = gen_helper_neon_cgt_f64; + break; + case 0x2d: /* FCMEQ (zero) */ + genfn = gen_helper_neon_ceq_f64; + break; + case 0x6d: /* FCMLE (zero) */ + swap = true; + /* fall through */ + case 0x6c: /* FCMGE (zero) */ + genfn = gen_helper_neon_cge_f64; + break; + default: + g_assert_not_reached(); + } + + for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) { + read_vec_element(s, tcg_op, rn, pass, MO_64); + if (swap) { + genfn(tcg_res, tcg_zero, tcg_op, fpst); + } else { + genfn(tcg_res, tcg_op, tcg_zero, fpst); + } + write_vec_element(s, tcg_res, rd, pass, MO_64); + } + if (is_scalar) { + clear_vec_high(s, rd); + } + + tcg_temp_free_i64(tcg_res); + tcg_temp_free_i64(tcg_zero); + tcg_temp_free_i64(tcg_op); + } else { + TCGv_i32 tcg_op = tcg_temp_new_i32(); + TCGv_i32 tcg_zero = tcg_const_i32(0); + TCGv_i32 tcg_res = tcg_temp_new_i32(); + NeonGenTwoSingleOPFn *genfn; + bool swap = false; + int pass, maxpasses; + + switch (opcode) { + case 0x2e: /* FCMLT (zero) */ + swap = true; + /* fall through */ + case 0x2c: /* FCMGT (zero) */ + genfn = gen_helper_neon_cgt_f32; + break; + case 0x2d: /* FCMEQ (zero) */ + genfn = gen_helper_neon_ceq_f32; + break; + case 0x6d: /* FCMLE (zero) */ + swap = true; + /* fall through */ + case 0x6c: /* FCMGE (zero) */ + genfn = gen_helper_neon_cge_f32; + break; + default: + g_assert_not_reached(); + } + + if (is_scalar) { + maxpasses = 1; + } else { + maxpasses = is_q ? 4 : 2; + } + + for (pass = 0; pass < maxpasses; pass++) { + read_vec_element_i32(s, tcg_op, rn, pass, MO_32); + if (swap) { + genfn(tcg_res, tcg_zero, tcg_op, fpst); + } else { + genfn(tcg_res, tcg_op, tcg_zero, fpst); + } + if (is_scalar) { + write_fp_sreg(s, rd, tcg_res); + } else { + write_vec_element_i32(s, tcg_res, rd, pass, MO_32); + } + } + tcg_temp_free_i32(tcg_res); + tcg_temp_free_i32(tcg_zero); + tcg_temp_free_i32(tcg_op); + if (!is_q && !is_scalar) { + clear_vec_high(s, rd); + } + } + + tcg_temp_free_ptr(fpst); +} + /* C3.6.12 AdvSIMD scalar two reg misc * 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0 * +-----+---+-----------+------+-----------+--------+-----+------+------+ @@ -6390,9 +6519,47 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn) return; } break; + case 0xc ... 0xf: + case 0x16 ... 0x1d: + case 0x1f: + /* Floating point: U, size[1] and opcode indicate operation; + * size[0] indicates single or double precision. + */ + opcode |= (extract32(size, 1, 1) << 5) | (u << 6); + size = extract32(size, 0, 1) ? 3 : 2; + switch (opcode) { + case 0x2c: /* FCMGT (zero) */ + case 0x2d: /* FCMEQ (zero) */ + case 0x2e: /* FCMLT (zero) */ + case 0x6c: /* FCMGE (zero) */ + case 0x6d: /* FCMLE (zero) */ + handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd); + return; + case 0x1a: /* FCVTNS */ + case 0x1b: /* FCVTMS */ + case 0x1c: /* FCVTAS */ + case 0x1d: /* SCVTF */ + case 0x3a: /* FCVTPS */ + case 0x3b: /* FCVTZS */ + case 0x3d: /* FRECPE */ + case 0x3f: /* FRECPX */ + case 0x56: /* FCVTXN, FCVTXN2 */ + case 0x5a: /* FCVTNU */ + case 0x5b: /* FCVTMU */ + case 0x5c: /* FCVTAU */ + case 0x5d: /* UCVTF */ + case 0x7a: /* FCVTPU */ + case 0x7b: /* FCVTZU */ + case 0x7d: /* FRSQRTE */ + unsupported_encoding(s, insn); + return; + default: + unallocated_encoding(s); + return; + } + break; default: /* Other categories of encoding in this class: - * + floating point (single and double) * + SUQADD/USQADD/SQABS/SQNEG : size 8, 16, 32 or 64 * + SQXTN/SQXTN2/SQXTUN/SQXTUN2/UQXTN/UQXTN2: * narrowing saturate ops: size 64/32/16 -> 32/16/8 @@ -7101,12 +7268,9 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn) unsupported_encoding(s, insn); return; case 0x1b: /* FMULX */ - case 0x1c: /* FCMEQ */ case 0x1f: /* FRECPS */ case 0x3f: /* FRSQRTS */ - case 0x5c: /* FCMGE */ case 0x5d: /* FACGE */ - case 0x7c: /* FCMGT */ case 0x7d: /* FACGT */ case 0x19: /* FMLA */ case 0x39: /* FMLS */ @@ -7114,13 +7278,16 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn) return; case 0x18: /* FMAXNM */ case 0x1a: /* FADD */ + case 0x1c: /* FCMEQ */ case 0x1e: /* FMAX */ case 0x38: /* FMINNM */ case 0x3a: /* FSUB */ case 0x3e: /* FMIN */ case 0x5b: /* FMUL */ + case 0x5c: /* FCMGE */ case 0x5f: /* FDIV */ case 0x7a: /* FABD */ + case 0x7c: /* FCMGT */ handle_3same_float(s, size, elements, fpopcode, rd, rn, rm); return; default: @@ -7700,6 +7867,17 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) return; } break; + case 0x2c: /* FCMGT (zero) */ + case 0x2d: /* FCMEQ (zero) */ + case 0x2e: /* FCMLT (zero) */ + case 0x6c: /* FCMGE (zero) */ + case 0x6d: /* FCMLE (zero) */ + if (size == 3 && !is_q) { + unallocated_encoding(s); + return; + } + handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd); + return; case 0x16: /* FCVTN, FCVTN2 */ case 0x17: /* FCVTL, FCVTL2 */ case 0x18: /* FRINTN */ @@ -7708,9 +7886,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) case 0x1b: /* FCVTMS */ case 0x1c: /* FCVTAS */ case 0x1d: /* SCVTF */ - case 0x2c: /* FCMGT (zero) */ - case 0x2d: /* FCMEQ (zero) */ - case 0x2e: /* FCMLT (zero) */ case 0x38: /* FRINTP */ case 0x39: /* FRINTZ */ case 0x3a: /* FCVTPS */ @@ -7724,8 +7899,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) case 0x5b: /* FCVTMU */ case 0x5c: /* FCVTAU */ case 0x5d: /* UCVTF */ - case 0x6c: /* FCMGE (zero) */ - case 0x6d: /* FCMLE (zero) */ case 0x79: /* FRINTI */ case 0x7a: /* FCVTPU */ case 0x7b: /* FCVTZU */