aboutsummaryrefslogtreecommitdiff
path: root/target/arm/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r--target/arm/translate.c240
1 files changed, 83 insertions, 157 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index c274c8b460..4750b9fa1b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -67,10 +67,6 @@ TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
TCGv_i64 cpu_exclusive_addr;
TCGv_i64 cpu_exclusive_val;
-/* FIXME: These should be removed. */
-static TCGv_i32 cpu_F0s, cpu_F1s;
-static TCGv_i64 cpu_F0d, cpu_F1d;
-
#include "exec/gen-icount.h"
static const char * const regnames[] =
@@ -80,6 +76,8 @@ static const char * const regnames[] =
/* Function prototypes for gen_ functions calling Neon helpers. */
typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
TCGv_i32, TCGv_i32);
+/* Function prototypes for gen_ functions for fix point conversions */
+typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
/* initialize TCG globals. */
void arm_translate_init(void)
@@ -1374,75 +1372,6 @@ static TCGv_ptr get_fpstatus_ptr(int neon)
return statusptr;
}
-static inline void gen_vfp_abs(int dp)
-{
- if (dp)
- gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
- else
- gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
-}
-
-static inline void gen_vfp_neg(int dp)
-{
- if (dp)
- gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
- else
- gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
-}
-
-#define VFP_GEN_ITOF(name) \
-static inline void gen_vfp_##name(int dp, int neon) \
-{ \
- TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
- if (dp) { \
- gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
- } else { \
- gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
- } \
- tcg_temp_free_ptr(statusptr); \
-}
-
-VFP_GEN_ITOF(uito)
-VFP_GEN_ITOF(sito)
-#undef VFP_GEN_ITOF
-
-#define VFP_GEN_FTOI(name) \
-static inline void gen_vfp_##name(int dp, int neon) \
-{ \
- TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
- if (dp) { \
- gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
- } else { \
- gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
- } \
- tcg_temp_free_ptr(statusptr); \
-}
-
-VFP_GEN_FTOI(touiz)
-VFP_GEN_FTOI(tosiz)
-#undef VFP_GEN_FTOI
-
-#define VFP_GEN_FIX(name, round) \
-static inline void gen_vfp_##name(int dp, int shift, int neon) \
-{ \
- TCGv_i32 tmp_shift = tcg_const_i32(shift); \
- TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
- if (dp) { \
- gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
- statusptr); \
- } else { \
- gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
- statusptr); \
- } \
- tcg_temp_free_i32(tmp_shift); \
- tcg_temp_free_ptr(statusptr); \
-}
-VFP_GEN_FIX(tosl, _round_to_zero)
-VFP_GEN_FIX(toul, _round_to_zero)
-VFP_GEN_FIX(slto, )
-VFP_GEN_FIX(ulto, )
-#undef VFP_GEN_FIX
-
static inline long vfp_reg_offset(bool dp, unsigned reg)
{
if (dp) {
@@ -1609,9 +1538,6 @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
return ret;
}
-#define tcg_gen_ld_f32 tcg_gen_ld_i32
-#define tcg_gen_st_f32 tcg_gen_st_i32
-
#define ARM_CP_RW_BIT (1 << 20)
/* Include the VFP decoder */
@@ -4189,16 +4115,6 @@ static const uint8_t neon_3r_sizes[] = {
#define NEON_2RM_VCVT_SF 62
#define NEON_2RM_VCVT_UF 63
-static int neon_2rm_is_float_op(int op)
-{
- /* Return true if this neon 2reg-misc op is float-to-float */
- return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
- (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
- op == NEON_2RM_VRINTM ||
- (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
- op >= NEON_2RM_VRECPE_F);
-}
-
static bool neon_2rm_is_v8_op(int op)
{
/* Return true if this neon 2reg-misc op is ARMv8 and up */
@@ -5779,28 +5695,41 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
}
} else if (op >= 14) {
/* VCVT fixed-point. */
+ TCGv_ptr fpst;
+ TCGv_i32 shiftv;
+ VFPGenFixPointFn *fn;
+
if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
return 1;
}
+
+ if (!(op & 1)) {
+ if (u) {
+ fn = gen_helper_vfp_ultos;
+ } else {
+ fn = gen_helper_vfp_sltos;
+ }
+ } else {
+ if (u) {
+ fn = gen_helper_vfp_touls_round_to_zero;
+ } else {
+ fn = gen_helper_vfp_tosls_round_to_zero;
+ }
+ }
+
/* We have already masked out the must-be-1 top bit of imm6,
* hence this 32-shift where the ARM ARM has 64-imm6.
*/
shift = 32 - shift;
+ fpst = get_fpstatus_ptr(1);
+ shiftv = tcg_const_i32(shift);
for (pass = 0; pass < (q ? 4 : 2); pass++) {
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
- if (!(op & 1)) {
- if (u)
- gen_vfp_ulto(0, shift, 1);
- else
- gen_vfp_slto(0, shift, 1);
- } else {
- if (u)
- gen_vfp_toul(0, shift, 1);
- else
- gen_vfp_tosl(0, shift, 1);
- }
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
+ TCGv_i32 tmpf = neon_load_reg(rm, pass);
+ fn(tmpf, tmpf, shiftv, fpst);
+ neon_store_reg(rd, pass, tmpf);
}
+ tcg_temp_free_ptr(fpst);
+ tcg_temp_free_i32(shiftv);
} else {
return 1;
}
@@ -6489,25 +6418,23 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
q || (rm & 1)) {
return 1;
}
- tmp = tcg_temp_new_i32();
- tmp2 = tcg_temp_new_i32();
fpst = get_fpstatus_ptr(true);
ahp = get_ahp_flag();
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
+ tmp = neon_load_reg(rm, 0);
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
+ tmp2 = neon_load_reg(rm, 1);
+ gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
tcg_gen_shli_i32(tmp2, tmp2, 16);
tcg_gen_or_i32(tmp2, tmp2, tmp);
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
- tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
+ tcg_temp_free_i32(tmp);
+ tmp = neon_load_reg(rm, 2);
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
+ tmp3 = neon_load_reg(rm, 3);
neon_store_reg(rd, 0, tmp2);
- tmp2 = tcg_temp_new_i32();
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
- tcg_gen_shli_i32(tmp2, tmp2, 16);
- tcg_gen_or_i32(tmp2, tmp2, tmp);
- neon_store_reg(rd, 1, tmp2);
+ gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
+ tcg_gen_shli_i32(tmp3, tmp3, 16);
+ tcg_gen_or_i32(tmp3, tmp3, tmp);
+ neon_store_reg(rd, 1, tmp3);
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(ahp);
tcg_temp_free_ptr(fpst);
@@ -6527,20 +6454,18 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
tmp = neon_load_reg(rm, 0);
tmp2 = neon_load_reg(rm, 1);
tcg_gen_ext16u_i32(tmp3, tmp);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
- tcg_gen_shri_i32(tmp3, tmp, 16);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
- tcg_temp_free_i32(tmp);
+ gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
+ neon_store_reg(rd, 0, tmp3);
+ tcg_gen_shri_i32(tmp, tmp, 16);
+ gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
+ neon_store_reg(rd, 1, tmp);
+ tmp3 = tcg_temp_new_i32();
tcg_gen_ext16u_i32(tmp3, tmp2);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
- tcg_gen_shri_i32(tmp3, tmp2, 16);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
- tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
- tcg_temp_free_i32(tmp2);
- tcg_temp_free_i32(tmp3);
+ gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
+ neon_store_reg(rd, 2, tmp3);
+ tcg_gen_shri_i32(tmp2, tmp2, 16);
+ gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
+ neon_store_reg(rd, 3, tmp2);
tcg_temp_free_i32(ahp);
tcg_temp_free_ptr(fpst);
break;
@@ -6614,13 +6539,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
default:
elementwise:
for (pass = 0; pass < (q ? 4 : 2); pass++) {
- if (neon_2rm_is_float_op(op)) {
- tcg_gen_ld_f32(cpu_F0s, cpu_env,
- neon_reg_offset(rm, pass));
- tmp = NULL;
- } else {
- tmp = neon_load_reg(rm, pass);
- }
+ tmp = neon_load_reg(rm, pass);
switch (op) {
case NEON_2RM_VREV32:
switch (size) {
@@ -6761,10 +6680,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
break;
}
case NEON_2RM_VABS_F:
- gen_vfp_abs(0);
+ gen_helper_vfp_abss(tmp, tmp);
break;
case NEON_2RM_VNEG_F:
- gen_vfp_neg(0);
+ gen_helper_vfp_negs(tmp, tmp);
break;
case NEON_2RM_VSWP:
tmp2 = neon_load_reg(rd, pass);
@@ -6798,7 +6717,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
cpu_env);
- gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
+ gen_helper_rints(tmp, tmp, fpstatus);
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
cpu_env);
tcg_temp_free_ptr(fpstatus);
@@ -6808,7 +6727,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
case NEON_2RM_VRINTX:
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
+ gen_helper_rints_exact(tmp, tmp, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
@@ -6832,10 +6751,10 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
cpu_env);
if (is_signed) {
- gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
+ gen_helper_vfp_tosls(tmp, tmp,
tcg_shift, fpst);
} else {
- gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
+ gen_helper_vfp_touls(tmp, tmp,
tcg_shift, fpst);
}
@@ -6863,41 +6782,52 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
case NEON_2RM_VRECPE_F:
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
+ gen_helper_recpe_f32(tmp, tmp, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
case NEON_2RM_VRSQRTE_F:
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
+ gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
tcg_temp_free_ptr(fpstatus);
break;
}
case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
- gen_vfp_sito(0, 1);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_vfp_sitos(tmp, tmp, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
- gen_vfp_uito(0, 1);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_vfp_uitos(tmp, tmp, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
- gen_vfp_tosiz(0, 1);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
- gen_vfp_touiz(0, 1);
+ {
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ gen_helper_vfp_touizs(tmp, tmp, fpstatus);
+ tcg_temp_free_ptr(fpstatus);
break;
+ }
default:
/* Reserved op values were caught by the
* neon_2rm_sizes[] check earlier.
*/
abort();
}
- if (neon_2rm_is_float_op(op)) {
- tcg_gen_st_f32(cpu_F0s, cpu_env,
- neon_reg_offset(rd, pass));
- } else {
- neon_store_reg(rd, pass, tmp);
- }
+ neon_store_reg(rd, pass, tmp);
}
break;
}
@@ -11977,12 +11907,8 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->base.max_insns = MIN(dc->base.max_insns, bound);
}
- cpu_F0s = tcg_temp_new_i32();
- cpu_F1s = tcg_temp_new_i32();
- cpu_F0d = tcg_temp_new_i64();
- cpu_F1d = tcg_temp_new_i64();
- cpu_V0 = cpu_F0d;
- cpu_V1 = cpu_F1d;
+ cpu_V0 = tcg_temp_new_i64();
+ cpu_V1 = tcg_temp_new_i64();
/* FIXME: cpu_M0 can probably be the same as cpu_V0. */
cpu_M0 = tcg_temp_new_i64();
}