From: Juha Riihimäki <juha.riihim...@nokia.com> Signed-Off-By: Riku Voipio <riku.voi...@nokia.com> Signed-off-by: Juha Riihimäki <juha.riihim...@nokia.com> --- target-arm/helpers.h | 4 +++ target-arm/neon_helper.c | 58 +++++++++++++++++++++++++++++++++++++++++---- target-arm/translate.c | 28 +++++++++++----------- 3 files changed, 70 insertions(+), 20 deletions(-)
diff --git a/target-arm/helpers.h b/target-arm/helpers.h index a5fd2e8..e1a8136 100644 --- a/target-arm/helpers.h +++ b/target-arm/helpers.h @@ -253,6 +253,10 @@ DEF_HELPER_3(neon_qshl_u32, i32, env, i32, i32) DEF_HELPER_3(neon_qshl_s32, i32, env, i32, i32) DEF_HELPER_3(neon_qshl_u64, i64, env, i64, i64) DEF_HELPER_3(neon_qshl_s64, i64, env, i64, i64) +DEF_HELPER_3(neon_qshlu_s8, i32, env, i32, i32) +DEF_HELPER_3(neon_qshlu_s16, i32, env, i32, i32) +DEF_HELPER_3(neon_qshlu_s32, i32, env, i32, i32) +DEF_HELPER_3(neon_qshlu_s64, i64, env, i64, i64) DEF_HELPER_3(neon_qrshl_u8, i32, env, i32, i32) DEF_HELPER_3(neon_qrshl_s8, i32, env, i32, i32) DEF_HELPER_3(neon_qrshl_u16, i32, env, i32, i32) diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 924bf40..7985293 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -600,8 +600,6 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) if (val) { val = ~(uint64_t)0; SET_QC(); - } else { - val = 0; } } else if (shift <= -64) { val = 0; @@ -622,9 +620,10 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) int8_t tmp; \ tmp = (int8_t)src2; \ if (tmp >= (ssize_t)sizeof(src1) * 8) { \ - if (src1) \ + if (src1) { \ SET_QC(); \ - dest = src1 >> 31; \ + } \ + dest = src1 ? ((uint32_t)(1 << (sizeof(src1) * 8 - 1)) - (src1 > 0 ? 1 : 0)) : 0; \ } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \ dest = src1 >> 31; \ } else if (tmp < 0) { \ @@ -633,7 +632,7 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) dest = src1 << tmp; \ if ((dest >> tmp) != src1) { \ SET_QC(); \ - dest = src2 >> 31; \ + dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)) - (src1 > 0 ? 1 : 0); \ } \ }} while (0) NEON_VOP_ENV(qshl_s8, neon_s8, 4) @@ -650,7 +649,7 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) SET_QC(); val = (val >> 63) & ~SIGNBIT64; } - } else if (shift <= 64) { + } else if (shift <= -64) { val >>= 63; } else if (shift < 0) { val >>= -shift; @@ -665,6 +664,53 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) return val; } +#define NEON_FN(dest, src1, src2) do { \ + if (src1 & (1 << (sizeof(src1) * 8 - 1))) { \ + SET_QC(); \ + dest = 0; \ + } else { \ + int8_t tmp; \ + tmp = (int8_t)src2; \ + if (tmp >= (ssize_t)sizeof(src1) * 8) { \ + if (src1) { \ + SET_QC(); \ + dest = ~0; \ + } else { \ + dest = 0; \ + } \ + } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \ + dest = 0; \ + } else if (tmp < 0) { \ + dest = src1 >> -tmp; \ + } else { \ + dest = src1 << tmp; \ + if ((dest >> tmp) != src1) { \ + SET_QC(); \ + dest = ~0; \ + } \ + } \ + }} while (0) +NEON_VOP_ENV(qshlu_s8, neon_u8, 4) +NEON_VOP_ENV(qshlu_s16, neon_u16, 2) +#undef NEON_FN + +uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop) +{ + if ((int32_t)valop < 0) { + SET_QC(); + return 0; + } + return helper_neon_qshl_u32(env, valop, shiftop); +} + +uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) +{ + if ((int64_t)valop < 0) { + SET_QC(); + return 0; + } + return helper_neon_qshl_u64(env, valop, shiftop); +} /* FIXME: This is wrong. */ #define NEON_FN(dest, src1, src2) do { \ diff --git a/target-arm/translate.c b/target-arm/translate.c index 26e6bf4..97fac4d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -4139,9 +4139,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) case 9: /* VQSHL */ if (u) { gen_helper_neon_qshl_u64(cpu_V0, cpu_env, - cpu_V0, cpu_V0); + cpu_V1, cpu_V0); } else { - gen_helper_neon_qshl_s64(cpu_V1, cpu_env, + gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V1, cpu_V0); } break; @@ -4612,10 +4612,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); break; case 6: /* VQSHLU */ - gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, - cpu_V1); + gen_helper_neon_qshlu_s64(cpu_V0, cpu_env, cpu_V0, + cpu_V1); break; - case 7: /* VQSHL/VQSHLU */ + case 7: /* VQSHL */ if (u) { gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1); @@ -4673,26 +4673,26 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) } break; case 6: /* VQSHLU */ - GEN_NEON_INTEGER_OP_ENV(qshl); - break; - case 7: /* VQSHLU */ switch (size) { case 0: - gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, - tmp2); + gen_helper_neon_qshlu_s8(tmp, cpu_env, tmp, + tmp2); break; case 1: - gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, - tmp2); + gen_helper_neon_qshlu_s16(tmp, cpu_env, tmp, + tmp2); break; case 2: - gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, - tmp2); + gen_helper_neon_qshlu_s32(tmp, cpu_env, tmp, + tmp2); break; default: abort(); /* size == 3 is handled earlier */ } break; + case 7: /* VQSHL */ + GEN_NEON_INTEGER_OP_ENV(qshl); + break; } tcg_temp_free_i32(tmp2); -- 1.6.5