target/arm: Implement VFP fp16 VMOV between gp and halfprec registers

Implement the VFP fp16 variant of VMOV that transfers a 16-bit
value between a general purpose register and a VFP register.

Note that Rt == 15 is UNPREDICTABLE; since this insn is v8 and later
only we have no need to replicate the old "updates CPSR.NZCV"
behaviour that the singleprec version of this insn does.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200828183354.27913-22-peter.maydell@linaro.org
master
Peter Maydell 2020-08-28 19:33:30 +01:00
parent f61e5c43b8
commit 46a4b85452
2 changed files with 35 additions and 0 deletions

View File

@ -809,6 +809,40 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
return true;
}
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
{
TCGv_i32 tmp;
if (!dc_isar_feature(aa32_fp16_arith, s)) {
return false;
}
if (a->rt == 15) {
/* UNPREDICTABLE; we choose to UNDEF */
return false;
}
if (!vfp_access_check(s)) {
return true;
}
if (a->l) {
/* VFP to general purpose register */
tmp = tcg_temp_new_i32();
neon_load_reg32(tmp, a->vn);
tcg_gen_andi_i32(tmp, tmp, 0xffff);
store_reg(s, a->rt, tmp);
} else {
/* general purpose register to VFP */
tmp = load_reg(s, a->rt);
tcg_gen_andi_i32(tmp, tmp, 0xffff);
neon_store_reg32(tmp, a->vn);
tcg_temp_free_i32(tmp);
}
return true;
}
static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
{
TCGv_i32 tmp;

View File

@ -74,6 +74,7 @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
vn=%vn_dp
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
VMOV_half ---- 1110 000 l:1 .... rt:4 1001 . 001 0000 vn=%vn_sp
VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp