@@ -509,9 +509,28 @@ uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop)
}} while (0)
NEON_VOP(rshl_s8, neon_s8, 4)
NEON_VOP(rshl_s16, neon_s16, 2)
-NEON_VOP(rshl_s32, neon_s32, 1)
#undef NEON_FN
+uint32_t HELPER(neon_rshl_s32)(uint32_t valop, uint32_t shiftop)
+{
+ int8_t shift =(int8_t)shiftop;
+ int32_t val = valop;
+ if (shift >= 32) {
+ val = 0;
+ } else if (shift < -32) {
+ val >>= 31;
+ } else if (shift == -32) {
+ val >>= 31;
+ val++;
+ val >>= 1;
+ } else if (shift < 0) {
+ val = ((int64_t)val + (1 << (-1 - shift))) >> -shift;
+ } else {
+ val <<= shift;
+ }
+ return val;
+}
+
uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
{
int8_t shift = (int8_t)shiftop;
@@ -520,7 +539,7 @@ uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
val = 0;
} else if (shift < -64) {
val >>= 63;
- } else if (shift == -63) {
+ } else if (shift == -64) {
val >>= 63;
val++;
val >>= 1;
@@ -4781,6 +4781,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
abort();
}
+ TCGV_UNUSED(tmp5);
for (pass = 0; pass < 2; pass++) {
if (size == 3) {
neon_load_reg64(cpu_V0, rm + pass);
@@ -4812,18 +4813,26 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
dead_tmp(tmp);
dead_tmp(tmp3);
}
- tmp = new_tmp();
+ tmp4 = new_tmp();
if (op == 8) {
if (u) { /* VQSHRUN / VQRSHRUN */
- gen_neon_unarrow_sats(size - 1, tmp, cpu_V0);
+ gen_neon_unarrow_sats(size - 1, tmp4, cpu_V0);
} else { /* VSHRN / VRSHRN */
- gen_neon_narrow(size - 1, tmp, cpu_V0);
+ gen_neon_narrow(size - 1, tmp4, cpu_V0);
}
} else { /* VQSHRN / VQRSHRN */
- gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
+ if (u) {
+ gen_neon_narrow_satu(size - 1, tmp4, cpu_V0);
+ } else {
+ gen_neon_narrow_sats(size - 1, tmp4, cpu_V0);
+ }
+ }
+ if (!pass) {
+ tmp5 = tmp4;
}
- neon_store_reg(rd, pass, tmp);
} /* for pass */
+ neon_store_reg(rd, 0, tmp5);
+ neon_store_reg(rd, 1, tmp4);
if (size == 3) {
tcg_temp_free_i64(tmp64);
} else {