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

Backports commit 46a4b854525cb9f34a611f6ada6cdff1eab0ac2d
This commit is contained in:
Peter Maydell 2021-03-01 16:26:32 -05:00 committed by Lioncash
parent 58485bca97
commit 08b70267d0
2 changed files with 36 additions and 0 deletions

View file

@ -819,6 +819,41 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
return true;
}
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
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(tcg_ctx);
neon_load_reg32(s, tmp, a->vn);
tcg_gen_andi_i32(tcg_ctx, 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(tcg_ctx, tmp, tmp, 0xffff);
neon_store_reg32(s, tmp, a->vn);
tcg_temp_free_i32(tcg_ctx, tmp);
}
return true;
}
static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;

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