target/arm: Move the VFP trans_* functions to translate-vfp.inc.c

Move the trans_*() functions we've just created from translate.c
to translate-vfp.inc.c. This is pure code motion with no textual
changes (this can be checked with 'git show --color-moved').

Backports commit f7bbb8f31f0761edbf0c64b7ab3c3f49c13612ea from qemu
This commit is contained in:
Peter Maydell 2019-06-13 16:56:21 -04:00 committed by Lioncash
parent e55d31a5ac
commit 033a386ffb
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 341 additions and 341 deletions

View file

@ -140,3 +140,344 @@ static bool vfp_access_check(DisasContext *s)
{
return full_vfp_access_check(s, false);
}
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rn, rm;
bool dp = a->dp;
if (!dc_isar_feature(aa32_vsel, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vn | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rn = a->vn;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
if (dp) {
TCGv_i64 frn, frm, dest;
TCGv_i64 tmp, zero, zf, nf, vf;
zero = tcg_const_i64(tcg_ctx, 0);
frn = tcg_temp_new_i64(tcg_ctx);
frm = tcg_temp_new_i64(tcg_ctx);
dest = tcg_temp_new_i64(tcg_ctx);
zf = tcg_temp_new_i64(tcg_ctx);
nf = tcg_temp_new_i64(tcg_ctx);
vf = tcg_temp_new_i64(tcg_ctx);
tcg_gen_extu_i32_i64(tcg_ctx, zf, tcg_ctx->cpu_ZF);
tcg_gen_ext_i32_i64(tcg_ctx, nf, tcg_ctx->cpu_NF);
tcg_gen_ext_i32_i64(tcg_ctx, vf, tcg_ctx->cpu_VF);
tcg_gen_ld_f64(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f64(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
switch (a->cc) {
case 0: /* eq: Z */
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_EQ, dest, zf, zero,
frn, frm);
break;
case 1: /* vs: V */
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_LT, dest, vf, zero,
frn, frm);
break;
case 2: /* ge: N == V -> N ^ V == 0 */
tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_xor_i64(tcg_ctx, tmp, vf, nf);
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
frn, frm);
tcg_temp_free_i64(tcg_ctx, tmp);
break;
case 3: /* gt: !Z && N == V */
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_NE, dest, zf, zero,
frn, frm);
tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_xor_i64(tcg_ctx, tmp, vf, nf);
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
dest, frm);
tcg_temp_free_i64(tcg_ctx, tmp);
break;
}
tcg_gen_st_f64(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(tcg_ctx, frn);
tcg_temp_free_i64(tcg_ctx, frm);
tcg_temp_free_i64(tcg_ctx, dest);
tcg_temp_free_i64(tcg_ctx, zf);
tcg_temp_free_i64(tcg_ctx, nf);
tcg_temp_free_i64(tcg_ctx, vf);
tcg_temp_free_i64(tcg_ctx, zero);
} else {
TCGv_i32 frn, frm, dest;
TCGv_i32 tmp, zero;
zero = tcg_const_i32(tcg_ctx, 0);
frn = tcg_temp_new_i32(tcg_ctx);
frm = tcg_temp_new_i32(tcg_ctx);
dest = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f32(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
switch (a->cc) {
case 0: /* eq: Z */
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_EQ, dest, tcg_ctx->cpu_ZF, zero,
frn, frm);
break;
case 1: /* vs: V */
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_LT, dest, tcg_ctx->cpu_VF, zero,
frn, frm);
break;
case 2: /* ge: N == V -> N ^ V == 0 */
tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF);
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
frn, frm);
tcg_temp_free_i32(tcg_ctx, tmp);
break;
case 3: /* gt: !Z && N == V */
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_NE, dest, tcg_ctx->cpu_ZF, zero,
frn, frm);
tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF);
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
dest, frm);
tcg_temp_free_i32(tcg_ctx, tmp);
break;
}
tcg_gen_st_f32(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(tcg_ctx, frn);
tcg_temp_free_i32(tcg_ctx, frm);
tcg_temp_free_i32(tcg_ctx, dest);
tcg_temp_free_i32(tcg_ctx, zero);
}
return true;
}
static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rn, rm;
bool dp = a->dp;
bool vmin = a->op;
TCGv_ptr fpst;
if (!dc_isar_feature(aa32_vminmaxnm, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vn | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rn = a->vn;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
fpst = get_fpstatus_ptr(s, 0);
if (dp) {
TCGv_i64 frn, frm, dest;
frn = tcg_temp_new_i64(tcg_ctx);
frm = tcg_temp_new_i64(tcg_ctx);
dest = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_f64(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f64(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
if (vmin) {
gen_helper_vfp_minnumd(tcg_ctx, dest, frn, frm, fpst);
} else {
gen_helper_vfp_maxnumd(tcg_ctx, dest, frn, frm, fpst);
}
tcg_gen_st_f64(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(tcg_ctx, frn);
tcg_temp_free_i64(tcg_ctx, frm);
tcg_temp_free_i64(tcg_ctx, dest);
} else {
TCGv_i32 frn, frm, dest;
frn = tcg_temp_new_i32(tcg_ctx);
frm = tcg_temp_new_i32(tcg_ctx);
dest = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f32(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
if (vmin) {
gen_helper_vfp_minnums(tcg_ctx, dest, frn, frm, fpst);
} else {
gen_helper_vfp_maxnums(tcg_ctx, dest, frn, frm, fpst);
}
tcg_gen_st_f32(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(tcg_ctx, frn);
tcg_temp_free_i32(tcg_ctx, frm);
tcg_temp_free_i32(tcg_ctx, dest);
}
tcg_temp_free_ptr(tcg_ctx, fpst);
return true;
}
/*
* Table for converting the most common AArch32 encoding of
* rounding mode to arm_fprounding order (which matches the
* common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
*/
static const uint8_t fp_decode_rm[] = {
FPROUNDING_TIEAWAY,
FPROUNDING_TIEEVEN,
FPROUNDING_POSINF,
FPROUNDING_NEGINF,
};
static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rm;
bool dp = a->dp;
TCGv_ptr fpst;
TCGv_i32 tcg_rmode;
int rounding = fp_decode_rm[a->rm];
if (!dc_isar_feature(aa32_vrint, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
fpst = get_fpstatus_ptr(s, 0);
tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(rounding));
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
if (dp) {
TCGv_i64 tcg_op;
TCGv_i64 tcg_res;
tcg_op = tcg_temp_new_i64(tcg_ctx);
tcg_res = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_f64(tcg_ctx, tcg_op, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
gen_helper_rintd(tcg_ctx, tcg_res, tcg_op, fpst);
tcg_gen_st_f64(tcg_ctx, tcg_res, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(tcg_ctx, tcg_op);
tcg_temp_free_i64(tcg_ctx, tcg_res);
} else {
TCGv_i32 tcg_op;
TCGv_i32 tcg_res;
tcg_op = tcg_temp_new_i32(tcg_ctx);
tcg_res = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, tcg_op, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
gen_helper_rints(tcg_ctx, tcg_res, tcg_op, fpst);
tcg_gen_st_f32(tcg_ctx, tcg_res, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(tcg_ctx, tcg_op);
tcg_temp_free_i32(tcg_ctx, tcg_res);
}
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
tcg_temp_free_i32(tcg_ctx, tcg_rmode);
tcg_temp_free_ptr(tcg_ctx, fpst);
return true;
}
static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rm;
bool dp = a->dp;
TCGv_ptr fpst;
TCGv_i32 tcg_rmode, tcg_shift;
int rounding = fp_decode_rm[a->rm];
bool is_signed = a->op;
if (!dc_isar_feature(aa32_vcvt_dr, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
return false;
}
rd = a->vd;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
fpst = get_fpstatus_ptr(s, 0);
tcg_shift = tcg_const_i32(tcg_ctx, 0);
tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(rounding));
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
if (dp) {
TCGv_i64 tcg_double, tcg_res;
TCGv_i32 tcg_tmp;
tcg_double = tcg_temp_new_i64(tcg_ctx);
tcg_res = tcg_temp_new_i64(tcg_ctx);
tcg_tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f64(tcg_ctx, tcg_double, tcg_ctx->cpu_env, vfp_reg_offset(1, rm));
if (is_signed) {
gen_helper_vfp_tosld(tcg_ctx, tcg_res, tcg_double, tcg_shift, fpst);
} else {
gen_helper_vfp_tould(tcg_ctx, tcg_res, tcg_double, tcg_shift, fpst);
}
tcg_gen_extrl_i64_i32(tcg_ctx, tcg_tmp, tcg_res);
tcg_gen_st_f32(tcg_ctx, tcg_tmp, tcg_ctx->cpu_env, vfp_reg_offset(0, rd));
tcg_temp_free_i32(tcg_ctx, tcg_tmp);
tcg_temp_free_i64(tcg_ctx, tcg_res);
tcg_temp_free_i64(tcg_ctx, tcg_double);
} else {
TCGv_i32 tcg_single, tcg_res;
tcg_single = tcg_temp_new_i32(tcg_ctx);
tcg_res = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, tcg_single, tcg_ctx->cpu_env, vfp_reg_offset(0, rm));
if (is_signed) {
gen_helper_vfp_tosls(tcg_ctx, tcg_res, tcg_single, tcg_shift, fpst);
} else {
gen_helper_vfp_touls(tcg_ctx, tcg_res, tcg_single, tcg_shift, fpst);
}
tcg_gen_st_f32(tcg_ctx, tcg_res, tcg_ctx->cpu_env, vfp_reg_offset(0, rd));
tcg_temp_free_i32(tcg_ctx, tcg_res);
tcg_temp_free_i32(tcg_ctx, tcg_single);
}
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
tcg_temp_free_i32(tcg_ctx, tcg_rmode);
tcg_temp_free_i32(tcg_ctx, tcg_shift);
tcg_temp_free_ptr(tcg_ctx, fpst);
return true;
}

View file

@ -3177,347 +3177,6 @@ static void gen_neon_dup_high16(DisasContext *s, TCGv_i32 var)
tcg_temp_free_i32(tcg_ctx, tmp);
}
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rn, rm;
bool dp = a->dp;
if (!dc_isar_feature(aa32_vsel, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vn | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rn = a->vn;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
if (dp) {
TCGv_i64 frn, frm, dest;
TCGv_i64 tmp, zero, zf, nf, vf;
zero = tcg_const_i64(tcg_ctx, 0);
frn = tcg_temp_new_i64(tcg_ctx);
frm = tcg_temp_new_i64(tcg_ctx);
dest = tcg_temp_new_i64(tcg_ctx);
zf = tcg_temp_new_i64(tcg_ctx);
nf = tcg_temp_new_i64(tcg_ctx);
vf = tcg_temp_new_i64(tcg_ctx);
tcg_gen_extu_i32_i64(tcg_ctx, zf, tcg_ctx->cpu_ZF);
tcg_gen_ext_i32_i64(tcg_ctx, nf, tcg_ctx->cpu_NF);
tcg_gen_ext_i32_i64(tcg_ctx, vf, tcg_ctx->cpu_VF);
tcg_gen_ld_f64(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f64(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
switch (a->cc) {
case 0: /* eq: Z */
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_EQ, dest, zf, zero,
frn, frm);
break;
case 1: /* vs: V */
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_LT, dest, vf, zero,
frn, frm);
break;
case 2: /* ge: N == V -> N ^ V == 0 */
tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_xor_i64(tcg_ctx, tmp, vf, nf);
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
frn, frm);
tcg_temp_free_i64(tcg_ctx, tmp);
break;
case 3: /* gt: !Z && N == V */
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_NE, dest, zf, zero,
frn, frm);
tmp = tcg_temp_new_i64(tcg_ctx);
tcg_gen_xor_i64(tcg_ctx, tmp, vf, nf);
tcg_gen_movcond_i64(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
dest, frm);
tcg_temp_free_i64(tcg_ctx, tmp);
break;
}
tcg_gen_st_f64(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(tcg_ctx, frn);
tcg_temp_free_i64(tcg_ctx, frm);
tcg_temp_free_i64(tcg_ctx, dest);
tcg_temp_free_i64(tcg_ctx, zf);
tcg_temp_free_i64(tcg_ctx, nf);
tcg_temp_free_i64(tcg_ctx, vf);
tcg_temp_free_i64(tcg_ctx, zero);
} else {
TCGv_i32 frn, frm, dest;
TCGv_i32 tmp, zero;
zero = tcg_const_i32(tcg_ctx, 0);
frn = tcg_temp_new_i32(tcg_ctx);
frm = tcg_temp_new_i32(tcg_ctx);
dest = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f32(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
switch (a->cc) {
case 0: /* eq: Z */
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_EQ, dest, tcg_ctx->cpu_ZF, zero,
frn, frm);
break;
case 1: /* vs: V */
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_LT, dest, tcg_ctx->cpu_VF, zero,
frn, frm);
break;
case 2: /* ge: N == V -> N ^ V == 0 */
tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF);
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
frn, frm);
tcg_temp_free_i32(tcg_ctx, tmp);
break;
case 3: /* gt: !Z && N == V */
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_NE, dest, tcg_ctx->cpu_ZF, zero,
frn, frm);
tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_xor_i32(tcg_ctx, tmp, tcg_ctx->cpu_VF, tcg_ctx->cpu_NF);
tcg_gen_movcond_i32(tcg_ctx, TCG_COND_GE, dest, tmp, zero,
dest, frm);
tcg_temp_free_i32(tcg_ctx, tmp);
break;
}
tcg_gen_st_f32(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(tcg_ctx, frn);
tcg_temp_free_i32(tcg_ctx, frm);
tcg_temp_free_i32(tcg_ctx, dest);
tcg_temp_free_i32(tcg_ctx, zero);
}
return true;
}
static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rn, rm;
bool dp = a->dp;
bool vmin = a->op;
TCGv_ptr fpst;
if (!dc_isar_feature(aa32_vminmaxnm, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vn | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rn = a->vn;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
fpst = get_fpstatus_ptr(s, 0);
if (dp) {
TCGv_i64 frn, frm, dest;
frn = tcg_temp_new_i64(tcg_ctx);
frm = tcg_temp_new_i64(tcg_ctx);
dest = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_f64(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f64(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
if (vmin) {
gen_helper_vfp_minnumd(tcg_ctx, dest, frn, frm, fpst);
} else {
gen_helper_vfp_maxnumd(tcg_ctx, dest, frn, frm, fpst);
}
tcg_gen_st_f64(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(tcg_ctx, frn);
tcg_temp_free_i64(tcg_ctx, frm);
tcg_temp_free_i64(tcg_ctx, dest);
} else {
TCGv_i32 frn, frm, dest;
frn = tcg_temp_new_i32(tcg_ctx);
frm = tcg_temp_new_i32(tcg_ctx);
dest = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, frn, tcg_ctx->cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f32(tcg_ctx, frm, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
if (vmin) {
gen_helper_vfp_minnums(tcg_ctx, dest, frn, frm, fpst);
} else {
gen_helper_vfp_maxnums(tcg_ctx, dest, frn, frm, fpst);
}
tcg_gen_st_f32(tcg_ctx, dest, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(tcg_ctx, frn);
tcg_temp_free_i32(tcg_ctx, frm);
tcg_temp_free_i32(tcg_ctx, dest);
}
tcg_temp_free_ptr(tcg_ctx, fpst);
return true;
}
/*
* Table for converting the most common AArch32 encoding of
* rounding mode to arm_fprounding order (which matches the
* common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
*/
static const uint8_t fp_decode_rm[] = {
FPROUNDING_TIEAWAY,
FPROUNDING_TIEEVEN,
FPROUNDING_POSINF,
FPROUNDING_NEGINF,
};
static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rm;
bool dp = a->dp;
TCGv_ptr fpst;
TCGv_i32 tcg_rmode;
int rounding = fp_decode_rm[a->rm];
if (!dc_isar_feature(aa32_vrint, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
fpst = get_fpstatus_ptr(s, 0);
tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(rounding));
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
if (dp) {
TCGv_i64 tcg_op;
TCGv_i64 tcg_res;
tcg_op = tcg_temp_new_i64(tcg_ctx);
tcg_res = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ld_f64(tcg_ctx, tcg_op, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
gen_helper_rintd(tcg_ctx, tcg_res, tcg_op, fpst);
tcg_gen_st_f64(tcg_ctx, tcg_res, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i64(tcg_ctx, tcg_op);
tcg_temp_free_i64(tcg_ctx, tcg_res);
} else {
TCGv_i32 tcg_op;
TCGv_i32 tcg_res;
tcg_op = tcg_temp_new_i32(tcg_ctx);
tcg_res = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, tcg_op, tcg_ctx->cpu_env, vfp_reg_offset(dp, rm));
gen_helper_rints(tcg_ctx, tcg_res, tcg_op, fpst);
tcg_gen_st_f32(tcg_ctx, tcg_res, tcg_ctx->cpu_env, vfp_reg_offset(dp, rd));
tcg_temp_free_i32(tcg_ctx, tcg_op);
tcg_temp_free_i32(tcg_ctx, tcg_res);
}
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
tcg_temp_free_i32(tcg_ctx, tcg_rmode);
tcg_temp_free_ptr(tcg_ctx, fpst);
return true;
}
static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
uint32_t rd, rm;
bool dp = a->dp;
TCGv_ptr fpst;
TCGv_i32 tcg_rmode, tcg_shift;
int rounding = fp_decode_rm[a->rm];
bool is_signed = a->op;
if (!dc_isar_feature(aa32_vcvt_dr, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
return false;
}
rd = a->vd;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
fpst = get_fpstatus_ptr(s, 0);
tcg_shift = tcg_const_i32(tcg_ctx, 0);
tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(rounding));
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
if (dp) {
TCGv_i64 tcg_double, tcg_res;
TCGv_i32 tcg_tmp;
tcg_double = tcg_temp_new_i64(tcg_ctx);
tcg_res = tcg_temp_new_i64(tcg_ctx);
tcg_tmp = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f64(tcg_ctx, tcg_double, tcg_ctx->cpu_env, vfp_reg_offset(1, rm));
if (is_signed) {
gen_helper_vfp_tosld(tcg_ctx, tcg_res, tcg_double, tcg_shift, fpst);
} else {
gen_helper_vfp_tould(tcg_ctx, tcg_res, tcg_double, tcg_shift, fpst);
}
tcg_gen_extrl_i64_i32(tcg_ctx, tcg_tmp, tcg_res);
tcg_gen_st_f32(tcg_ctx, tcg_tmp, tcg_ctx->cpu_env, vfp_reg_offset(0, rd));
tcg_temp_free_i32(tcg_ctx, tcg_tmp);
tcg_temp_free_i64(tcg_ctx, tcg_res);
tcg_temp_free_i64(tcg_ctx, tcg_double);
} else {
TCGv_i32 tcg_single, tcg_res;
tcg_single = tcg_temp_new_i32(tcg_ctx);
tcg_res = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ld_f32(tcg_ctx, tcg_single, tcg_ctx->cpu_env, vfp_reg_offset(0, rm));
if (is_signed) {
gen_helper_vfp_tosls(tcg_ctx, tcg_res, tcg_single, tcg_shift, fpst);
} else {
gen_helper_vfp_touls(tcg_ctx, tcg_res, tcg_single, tcg_shift, fpst);
}
tcg_gen_st_f32(tcg_ctx, tcg_res, tcg_ctx->cpu_env, vfp_reg_offset(0, rd));
tcg_temp_free_i32(tcg_ctx, tcg_res);
tcg_temp_free_i32(tcg_ctx, tcg_single);
}
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, fpst);
tcg_temp_free_i32(tcg_ctx, tcg_rmode);
tcg_temp_free_i32(tcg_ctx, tcg_shift);
tcg_temp_free_ptr(tcg_ctx, fpst);
return true;
}
/*
* Disassemble a VFP instruction. Returns nonzero if an error occurred
* (ie. an undefined instruction).