From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=48437 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PiqbT-0005Og-NJ for qemu-devel@nongnu.org; Fri, 28 Jan 2011 10:51:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PiqbR-0000zu-Lo for qemu-devel@nongnu.org; Fri, 28 Jan 2011 10:51:15 -0500 Received: from eu1sys200aog110.obsmtp.com ([207.126.144.129]:45202) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PiqbR-0000zB-9b for qemu-devel@nongnu.org; Fri, 28 Jan 2011 10:51:13 -0500 Received: from zeta.dmz-eu.st.com (ns2.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 252B9211 for ; Fri, 28 Jan 2011 15:51:11 +0000 (GMT) Received: from Webmail-eu.st.com (safex1hubcas5.st.com [10.75.90.71]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0CC692B0B for ; Fri, 28 Jan 2011 15:51:11 +0000 (GMT) From: Date: Fri, 28 Jan 2011 16:51:00 +0100 Message-ID: <1296229866-32011-3-git-send-email-christophe.lyon@st.com> In-Reply-To: <1296229866-32011-1-git-send-email-christophe.lyon@st.com> References: <1296229866-32011-1-git-send-email-christophe.lyon@st.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH 2/8] target-arm: Create and use neon_unarrow_sat* helpers List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org From: Christophe Lyon Fix VQMOVUN, improve VQSHRUN and VQRSHRUN. Signed-off-by: Peter Maydell Signed-off-by: Christophe Lyon --- target-arm/helpers.h | 3 ++ target-arm/neon_helper.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ target-arm/translate.c | 43 ++++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/target-arm/helpers.h b/target-arm/helpers.h index 8a2564e..4d0de00 100644 --- a/target-arm/helpers.h +++ b/target-arm/helpers.h @@ -299,10 +299,13 @@ DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32) DEF_HELPER_1(neon_narrow_u8, i32, i64) DEF_HELPER_1(neon_narrow_u16, i32, i64) +DEF_HELPER_2(neon_unarrow_sat8, i32, env, i64) DEF_HELPER_2(neon_narrow_sat_u8, i32, env, i64) DEF_HELPER_2(neon_narrow_sat_s8, i32, env, i64) +DEF_HELPER_2(neon_unarrow_sat16, i32, env, i64) DEF_HELPER_2(neon_narrow_sat_u16, i32, env, i64) DEF_HELPER_2(neon_narrow_sat_s16, i32, env, i64) +DEF_HELPER_2(neon_unarrow_sat32, i32, env, i64) DEF_HELPER_2(neon_narrow_sat_u32, i32, env, i64) DEF_HELPER_2(neon_narrow_sat_s32, i32, env, i64) DEF_HELPER_1(neon_narrow_high_u8, i32, i64) diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 5971275..71e3c74 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -1094,6 +1094,33 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x) return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000); } +uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x) +{ + uint16_t s; + uint8_t d; + uint32_t res = 0; +#define SAT8(n) \ + s = x >> n; \ + if (s & 0x8000) { \ + SET_QC(); \ + } else { \ + if (s > 0xff) { \ + d = 0xff; \ + SET_QC(); \ + } else { \ + d = s; \ + } \ + res |= (uint32_t)d << (n / 2); \ + } + + SAT8(0); + SAT8(16); + SAT8(32); + SAT8(48); +#undef SAT8 + return res; +} + uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x) { uint16_t s; @@ -1140,6 +1167,29 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x) return res; } +uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x) +{ + uint32_t high; + uint32_t low; + low = x; + if (low & 0x80000000) { + low = 0; + SET_QC(); + } else if (low > 0xffff) { + low = 0xffff; + SET_QC(); + } + high = x >> 32; + if (high & 0x80000000) { + high = 0; + SET_QC(); + } else if (high > 0xffff) { + high = 0xffff; + SET_QC(); + } + return low | (high << 16); +} + uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x) { uint32_t high; @@ -1174,6 +1224,19 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x) return (uint16_t)low | (high << 16); } +uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x) +{ + if (x & 0x8000000000000000ull) { + SET_QC(); + return 0; + } + if (x > 0xffffffffu) { + SET_QC(); + return 0xffffffffu; + } + return x; +} + uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x) { if (x > 0xffffffffu) { diff --git a/target-arm/translate.c b/target-arm/translate.c index b14fa4b..cda5a73 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -4078,6 +4078,16 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) } } +static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) +{ + switch(size) { + case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break; + case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break; + case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break; + default: abort(); + } +} + static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, int q, int u) { @@ -4852,13 +4862,14 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) dead_tmp(tmp3); } tmp = new_tmp(); - if (op == 8 && !u) { - gen_neon_narrow(size - 1, tmp, cpu_V0); - } else { - if (op == 8) - gen_neon_narrow_sats(size - 1, tmp, cpu_V0); - else - gen_neon_narrow_satu(size - 1, tmp, cpu_V0); + if (op == 8) { + if (u) { /* VQSHRUN / VQRSHRUN */ + gen_neon_unarrow_sats(size - 1, tmp, cpu_V0); + } else { /* VSHRN / VRSHRN */ + gen_neon_narrow(size - 1, tmp, cpu_V0); + } + } else { /* VQSHRN / VQRSHRN */ + gen_neon_narrow_satu(size - 1, tmp, cpu_V0); } neon_store_reg(rd, pass, tmp); } /* for pass */ @@ -5485,12 +5496,18 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) for (pass = 0; pass < 2; pass++) { neon_load_reg64(cpu_V0, rm + pass); tmp = new_tmp(); - if (op == 36 && q == 0) { - gen_neon_narrow(size, tmp, cpu_V0); - } else if (q) { - gen_neon_narrow_satu(size, tmp, cpu_V0); - } else { - gen_neon_narrow_sats(size, tmp, cpu_V0); + if (op == 36) { + if (q) { /* VQMOVUN */ + gen_neon_unarrow_sats(size, tmp, cpu_V0); + } else { /* VMOVN */ + gen_neon_narrow(size, tmp, cpu_V0); + } + } else { /* VQMOVN */ + if (q) { + gen_neon_narrow_satu(size, tmp, cpu_V0); + } else { + gen_neon_narrow_sats(size, tmp, cpu_V0); + } } if (pass == 0) { tmp2 = tmp; -- 1.7.2.3