mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-22 20:51:08 +00:00
target/arm: Convert VCVT fp/fixed-point conversion insns to decodetree
Convert the VCVT (between floating-point and fixed-point) instructions to decodetree. Backports commit e3d6f4290c788e850c64815f0b3e331600a4bcc0 from qemu
This commit is contained in:
parent
c66d477359
commit
f6c67559d4
|
@ -2496,3 +2496,129 @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
|
|||
tcg_temp_free_i32(tcg_ctx, vd);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
TCGv_i32 vd, shift;
|
||||
TCGv_ptr fpst;
|
||||
int frac_bits;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vfp_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
|
||||
|
||||
vd = tcg_temp_new_i32(tcg_ctx);
|
||||
neon_load_reg32(s, vd, a->vd);
|
||||
|
||||
fpst = get_fpstatus_ptr(s, false);
|
||||
shift = tcg_const_i32(tcg_ctx, frac_bits);
|
||||
|
||||
/* Switch on op:U:sx bits */
|
||||
switch (a->opc) {
|
||||
case 0:
|
||||
gen_helper_vfp_shtos(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 1:
|
||||
gen_helper_vfp_sltos(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 2:
|
||||
gen_helper_vfp_uhtos(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 3:
|
||||
gen_helper_vfp_ultos(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 4:
|
||||
gen_helper_vfp_toshs_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 5:
|
||||
gen_helper_vfp_tosls_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 6:
|
||||
gen_helper_vfp_touhs_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 7:
|
||||
gen_helper_vfp_touls_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
neon_store_reg32(s, vd, a->vd);
|
||||
tcg_temp_free_i32(tcg_ctx, vd);
|
||||
tcg_temp_free_i32(tcg_ctx, shift);
|
||||
tcg_temp_free_ptr(tcg_ctx, fpst);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
TCGv_i64 vd;
|
||||
TCGv_i32 shift;
|
||||
TCGv_ptr fpst;
|
||||
int frac_bits;
|
||||
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* UNDEF accesses to D16-D31 if they don't exist. */
|
||||
if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vfp_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
|
||||
|
||||
vd = tcg_temp_new_i64(tcg_ctx);
|
||||
neon_load_reg64(s, vd, a->vd);
|
||||
|
||||
fpst = get_fpstatus_ptr(s, false);
|
||||
shift = tcg_const_i32(tcg_ctx, frac_bits);
|
||||
|
||||
/* Switch on op:U:sx bits */
|
||||
switch (a->opc) {
|
||||
case 0:
|
||||
gen_helper_vfp_shtod(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 1:
|
||||
gen_helper_vfp_sltod(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 2:
|
||||
gen_helper_vfp_uhtod(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 3:
|
||||
gen_helper_vfp_ultod(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 4:
|
||||
gen_helper_vfp_toshd_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 5:
|
||||
gen_helper_vfp_tosld_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 6:
|
||||
gen_helper_vfp_touhd_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
case 7:
|
||||
gen_helper_vfp_tould_round_to_zero(tcg_ctx, vd, vd, shift, fpst);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
neon_store_reg64(s, vd, a->vd);
|
||||
tcg_temp_free_i64(tcg_ctx, vd);
|
||||
tcg_temp_free_i32(tcg_ctx, shift);
|
||||
tcg_temp_free_ptr(tcg_ctx, fpst);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1499,13 +1499,9 @@ static inline void gen_vfp_##name(DisasContext *s, int dp, int shift, int neon)
|
|||
tcg_temp_free_i32(tcg_ctx, tmp_shift); \
|
||||
tcg_temp_free_ptr(tcg_ctx, statusptr); \
|
||||
}
|
||||
VFP_GEN_FIX(tosh, _round_to_zero)
|
||||
VFP_GEN_FIX(tosl, _round_to_zero)
|
||||
VFP_GEN_FIX(touh, _round_to_zero)
|
||||
VFP_GEN_FIX(toul, _round_to_zero)
|
||||
VFP_GEN_FIX(shto, )
|
||||
VFP_GEN_FIX(slto, )
|
||||
VFP_GEN_FIX(uhto, )
|
||||
VFP_GEN_FIX(ulto, )
|
||||
#undef VFP_GEN_FIX
|
||||
|
||||
|
@ -3144,7 +3140,8 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
return 1;
|
||||
case 15:
|
||||
switch (rn) {
|
||||
case 0 ... 19:
|
||||
case 0 ... 23:
|
||||
case 28 ... 31:
|
||||
/* Already handled by decodetree */
|
||||
return 1;
|
||||
default:
|
||||
|
@ -3164,21 +3161,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
rd_is_dp = false;
|
||||
break;
|
||||
|
||||
case 0x14: /* vcvt fp <-> fixed */
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
|
||||
return 1;
|
||||
}
|
||||
/* Immediate frac_bits has same format as SREG_M. */
|
||||
rm_is_dp = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
@ -3237,17 +3219,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
/* Load the initial operands. */
|
||||
if (op == 15) {
|
||||
switch (rn) {
|
||||
case 0x14: /* vcvt fp <-> fixed */
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
/* Source and destination the same. */
|
||||
gen_mov_F0_vreg(s, dp, rd);
|
||||
break;
|
||||
default:
|
||||
/* One source operand. */
|
||||
gen_mov_F0_vreg(s, rm_is_dp, rm);
|
||||
|
@ -3264,18 +3235,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
switch (op) {
|
||||
case 15: /* extension space */
|
||||
switch (rn) {
|
||||
case 20: /* fshto */
|
||||
gen_vfp_shto(s, dp, 16 - rm, 0);
|
||||
break;
|
||||
case 21: /* fslto */
|
||||
gen_vfp_slto(s, dp, 32 - rm, 0);
|
||||
break;
|
||||
case 22: /* fuhto */
|
||||
gen_vfp_uhto(s, dp, 16 - rm, 0);
|
||||
break;
|
||||
case 23: /* fulto */
|
||||
gen_vfp_ulto(s, dp, 32 - rm, 0);
|
||||
break;
|
||||
case 24: /* ftoui */
|
||||
gen_vfp_toui(s, dp, 0);
|
||||
break;
|
||||
|
@ -3288,18 +3247,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
|||
case 27: /* ftosiz */
|
||||
gen_vfp_tosiz(s, dp, 0);
|
||||
break;
|
||||
case 28: /* ftosh */
|
||||
gen_vfp_tosh(s, dp, 16 - rm, 0);
|
||||
break;
|
||||
case 29: /* ftosl */
|
||||
gen_vfp_tosl(s, dp, 32 - rm, 0);
|
||||
break;
|
||||
case 30: /* ftouh */
|
||||
gen_vfp_touh(s, dp, 16 - rm, 0);
|
||||
break;
|
||||
case 31: /* ftoul */
|
||||
gen_vfp_toul(s, dp, 32 - rm, 0);
|
||||
break;
|
||||
default: /* undefined */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
|
|
@ -224,3 +224,13 @@ VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
|
|||
# VJCVT is always dp to sp
|
||||
VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... \
|
||||
vd=%vd_sp vm=%vm_dp
|
||||
|
||||
# VCVT between floating-point and fixed-point. The immediate value
|
||||
# is in the same format as a Vm single-precision register number.
|
||||
# We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field
|
||||
# for the convenience of the trans_VCVT_fix functions.
|
||||
%vcvt_fix_op 18:1 16:1 7:1
|
||||
VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \
|
||||
vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
|
||||
VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
|
||||
vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op
|
||||
|
|
Loading…
Reference in a new issue