target-arm: Handle UNDEF cases for Neon "2 regs and shift" insns

Correctly handle all the UNDEF cases for Neon instructions of the
"2 registers and shift" form, and make sure that we check for these
cases early enough not to leak TCG temporaries.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Peter Maydell 2011-04-11 16:26:14 +01:00 committed by Aurelien Jarno
parent a5a14945da
commit cc13115bde
1 changed files with 22 additions and 19 deletions

View File

@ -4744,7 +4744,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
/* Two registers and shift. */ /* Two registers and shift. */
op = (insn >> 8) & 0xf; op = (insn >> 8) & 0xf;
if (insn & (1 << 7)) { if (insn & (1 << 7)) {
/* 64-bit shift. */ /* 64-bit shift. */
if (op > 7) {
return 1;
}
size = 3; size = 3;
} else { } else {
size = 2; size = 2;
@ -4757,6 +4760,12 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
if (op < 8) { if (op < 8) {
/* Shift by immediate: /* Shift by immediate:
VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */ VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
if (q && ((rd | rm) & 1)) {
return 1;
}
if (!u && (op == 4 || op == 6)) {
return 1;
}
/* Right shifts are encoded as N - shift, where N is the /* Right shifts are encoded as N - shift, where N is the
element size in bits. */ element size in bits. */
if (op <= 4) if (op <= 4)
@ -4804,20 +4813,13 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1); gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
break; break;
case 4: /* VSRI */ case 4: /* VSRI */
if (!u)
return 1;
gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
break; break;
case 5: /* VSHL, VSLI */ case 5: /* VSHL, VSLI */
gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
break; break;
case 6: /* VQSHLU */ case 6: /* VQSHLU */
if (u) { gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1);
gen_helper_neon_qshlu_s64(cpu_V0,
cpu_V0, cpu_V1);
} else {
return 1;
}
break; break;
case 7: /* VQSHL */ case 7: /* VQSHL */
if (u) { if (u) {
@ -4865,8 +4867,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
GEN_NEON_INTEGER_OP(rshl); GEN_NEON_INTEGER_OP(rshl);
break; break;
case 4: /* VSRI */ case 4: /* VSRI */
if (!u)
return 1;
GEN_NEON_INTEGER_OP(shl); GEN_NEON_INTEGER_OP(shl);
break; break;
case 5: /* VSHL, VSLI */ case 5: /* VSHL, VSLI */
@ -4874,13 +4874,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break; case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break; case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break; case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
default: return 1; default: abort();
} }
break; break;
case 6: /* VQSHLU */ case 6: /* VQSHLU */
if (!u) {
return 1;
}
switch (size) { switch (size) {
case 0: case 0:
gen_helper_neon_qshlu_s8(tmp, tmp, tmp2); gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
@ -4892,7 +4889,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_helper_neon_qshlu_s32(tmp, tmp, tmp2); gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
break; break;
default: default:
return 1; abort();
} }
break; break;
case 7: /* VQSHL */ case 7: /* VQSHL */
@ -4950,7 +4947,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
/* Shift by immediate and narrow: /* Shift by immediate and narrow:
VSHRN, VRSHRN, VQSHRN, VQRSHRN. */ VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
int input_unsigned = (op == 8) ? !u : u; int input_unsigned = (op == 8) ? !u : u;
if (rm & 1) {
return 1;
}
shift = shift - (1 << (size + 3)); shift = shift - (1 << (size + 3));
size++; size++;
if (size == 3) { if (size == 3) {
@ -5018,9 +5017,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp2);
} }
} else if (op == 10) { } else if (op == 10) {
/* VSHLL */ /* VSHLL, VMOVL */
if (q || size == 3) if (q || (rd & 1)) {
return 1; return 1;
}
tmp = neon_load_reg(rm, 0); tmp = neon_load_reg(rm, 0);
tmp2 = neon_load_reg(rm, 1); tmp2 = neon_load_reg(rm, 1);
for (pass = 0; pass < 2; pass++) { for (pass = 0; pass < 2; pass++) {
@ -5061,6 +5061,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
} }
} else if (op >= 14) { } else if (op >= 14) {
/* VCVT fixed-point. */ /* VCVT fixed-point. */
if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
return 1;
}
/* We have already masked out the must-be-1 top bit of imm6, /* We have already masked out the must-be-1 top bit of imm6,
* hence this 32-shift where the ARM ARM has 64-imm6. * hence this 32-shift where the ARM ARM has 64-imm6.
*/ */