diff --git a/qemu/target/arm/translate-vfp.inc.c b/qemu/target/arm/translate-vfp.inc.c index ff0c31a7..bbe75dfd 100644 --- a/qemu/target/arm/translate-vfp.inc.c +++ b/qemu/target/arm/translate-vfp.inc.c @@ -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; diff --git a/qemu/target/arm/vfp.decode b/qemu/target/arm/vfp.decode index 9a79e99f..51f143b4 100644 --- a/qemu/target/arm/vfp.decode +++ b/qemu/target/arm/vfp.decode @@ -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